<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: aruna-x</title>
    <description>The latest articles on DEV Community by aruna-x (@aruna).</description>
    <link>https://dev.to/aruna</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F744146%2F9920abb3-d96c-4003-918f-382230018c7d.jpg</url>
      <title>DEV Community: aruna-x</title>
      <link>https://dev.to/aruna</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aruna"/>
    <language>en</language>
    <item>
      <title>Sometimes Stochastic Parrots Lie: How to Minimize LLM Hallucinations</title>
      <dc:creator>aruna-x</dc:creator>
      <pubDate>Thu, 08 Jun 2023 07:32:33 +0000</pubDate>
      <link>https://dev.to/aruna/how-to-minimize-llm-hallucinations-2el7</link>
      <guid>https://dev.to/aruna/how-to-minimize-llm-hallucinations-2el7</guid>
      <description>&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Examples of LLM Hallucinations&lt;/li&gt;
&lt;li&gt;Why Do LLMs Hallucinate?&lt;/li&gt;
&lt;li&gt;
Strategies to Mitigate Hallucinations

&lt;ul&gt;
&lt;li&gt;Steerability&lt;/li&gt;
&lt;li&gt;Retrieval Data Augmentation&lt;/li&gt;
&lt;li&gt;Completion Parameters / Hyperparameters&lt;/li&gt;
&lt;li&gt;Chain-of-Thought (CoT) Prompting&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




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

&lt;p&gt;This week I prompted &lt;a href="https://openai.com/blog/chatgpt" rel="noopener noreferrer"&gt;ChatGPT&lt;/a&gt; to educate me about &lt;em&gt;LLM hallucinations&lt;/em&gt;. Hilariously, it hallucinated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffc6w2qil6av3o0nlvlqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffc6w2qil6av3o0nlvlqy.png" alt="ChatGPT completion about Late-Life Migraines"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Late-life migraine accompaniments exist, however 'LLM' is not a valid acronym referencing them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foype5vsrwehljttajsnw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foype5vsrwehljttajsnw.png" alt="Sparse Google results 'late-life migraine "&gt;&lt;/a&gt;&lt;br&gt;
(Various permutations of this query were similarly fruitless.)&lt;/p&gt;

&lt;p&gt;Despite its penchant for false facts, ChatGPT is not a malignant sociopath poised to betray us all. (I'm looking at you, &lt;a href="https://en.wikipedia.org/wiki/HAL_9000" rel="noopener noreferrer"&gt;Hal&lt;/a&gt;.) LLMs don't have intent. They produce outputs, and we label those offerings acceptable or hallucinatory based on our own valence toward them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples of LLM Hallucinations &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Have you heard that ChatGPT taught itself advanced Chemistry? Turns out, &lt;a href="https://twitter.com/boneillhawk/status/1640341209582391301?ref=thestack.technology" rel="noopener noreferrer"&gt;it didn't&lt;/a&gt;. It can simply double-talk advanced Chemistry convincingly enough to impress a layperson.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Watch ChatGPT &lt;a href="https://www.reddit.com/r/ProgrammerHumor/comments/13sfn1j/chatgpt_gaslighted_me_hard_so_i_gaslighted_it/" rel="noopener noreferrer"&gt;'gaslight' a user&lt;/a&gt; about the date.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In March of 2023 Stanford researchers published a &lt;a href="https://ai.facebook.com/blog/large-language-model-llama-meta-ai/" rel="noopener noreferrer"&gt;LLaMa&lt;/a&gt;-based chatbot, only to &lt;a href="https://www.techspot.com/news/98022-stanford-pulls-alpaca-chatbot-citing-hallucinations-costs-safety.html" rel="noopener noreferrer"&gt;quickly take it down&lt;/a&gt; due to hallucination.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A lovely kaleidoscope of fever dreams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ihz2uoao3sn8funhbv4.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ihz2uoao3sn8funhbv4.jpeg" alt="Meme of George from Seinfeld saying, "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do LLMs Hallucinate? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There are two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lack of information.&lt;/li&gt;
&lt;li&gt;A surface level, statistical model of language, rather than a modicum of true semantic understanding.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An LLM is liable to hallucinate when it lacks sufficient, domain-specific data during the training phase. Every LLM must be trained on a large corpus of knowledge long before it is made available to an end user. &lt;strong&gt;ChatGPT, for example, had access to the internet until its 'knowledge cutoff' in September 2021.&lt;/strong&gt; (Although confusingly it seems to know about &lt;a href="https://www.semafor.com/article/01/12/2023/chatgpt-knows-elon-musk-is-twitters-ceo-despite-saying-its-learning-cutoff-was-in-2021" rel="noopener noreferrer"&gt;events that occurred after then&lt;/a&gt;. Mystery.)&lt;/p&gt;

&lt;p&gt;As of September 2021, LLM hallucinations were not widely discussed online. &lt;/p&gt;

&lt;p&gt;Whether or not it has enough subject material, &lt;strong&gt;LLMs are designed to complete what a human is &lt;em&gt;likely&lt;/em&gt; to say, not necessarily what's correct.&lt;/strong&gt; The use of statistical likelihood in Natural Language and text generation is nothing new. &lt;a href="https://www.cs.princeton.edu/courses/archive/spr05/cos126/assignments/markov.html" rel="noopener noreferrer"&gt;Markov chains&lt;/a&gt;, for instance, have been helpful in this domain for years. Natural Language Processing (NLP) and AI experts often call LLMs 'stochastic parrots'. Somewhat hilariously diminutive, given that LLMs can have billions of parameters - but totally fair.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4us2vsl3f56j85ju9fqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4us2vsl3f56j85ju9fqz.png" alt="Showing the probability of ' jumped' in the sentence "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that probabilities are calculated for &lt;em&gt;tokens&lt;/em&gt; not words. Distinct tokens represent 'jumped' and ' jumped' (with a space). In this case, the probability of "jumped" is 82.14%.&lt;/p&gt;

&lt;p&gt;In the second, deterministically repeated sentence, "jumped" occurs with 100% probability. Of course.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felpz896a1r4mjixca8ux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felpz896a1r4mjixca8ux.png" alt="Showing the probability of 'jumped' in the repeated sentence "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we can make a leap from here, the point is: In a very general sense the sentence "The cow jumped over the moon" is as &lt;em&gt;correct&lt;/em&gt; to an LLM as "Water boils at 100 degrees Celsius or 212 degrees Fahrenheit" - even though one is fantasy and the other is factual.&lt;/p&gt;

&lt;p&gt;Now let's put the two pieces together. If ChatGPT doesn't know current events, it doesn't have information about LLM hallucinations. And if it is trained to spit out &lt;a href="https://thegradient.pub/othello/" rel="noopener noreferrer"&gt;statistically likely&lt;/a&gt; phrases regardless of whether it has the &lt;em&gt;facts&lt;/em&gt;, we get fabrications.&lt;/p&gt;

&lt;p&gt;According to Ed Targett in this compelling &lt;a href="https://www.thestack.technology/the-big-hallucination-large-language-models-consciousness/" rel="noopener noreferrer"&gt;article on LLM Hallucinations&lt;/a&gt;, "an eagerness to ascribe intelligence to LLMs comes with the risk that we start consuming convincing black box outputs as gospel without rigorous diligence." To that I say: Amen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strategies to Mitigate Hallucinations &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As of writing this article, these post-training user strategies have proven effective:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Steerability via prompting&lt;/li&gt;
&lt;li&gt;Retrieval data augmentation&lt;/li&gt;
&lt;li&gt;Completion parameters / hyperparameters&lt;/li&gt;
&lt;li&gt;Chain-of-Thought (CoT) prompting&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Steerability &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Steerability is the ability to guide an LLM's behavior. The LLM can take on a role: "You are a chemistry teacher." Or it can follow instructions: "Make a list of the 5 best places to vacation if you are allergic to the sun." (True story. I have two sun allergies.)&lt;/p&gt;

&lt;p&gt;It can also adopt a persona or tone: "Summarize Edgar Allen Poe's The Tell-Tale Heart in the tone of Cardi B."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tk4fuybglny9wfhddrl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tk4fuybglny9wfhddrl.png" alt="A ChatGPT completion of a summary of Edgar Allen Poe's The Tell-Tale Heart in the tone of Cardi B"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks Cardi, that ending really turned it into an upper. &lt;/p&gt;

&lt;p&gt;Note that currently ChatGPT uses GPT-3.5 under the hood. GPT-4 however is much &lt;a href="https://twitter.com/cwolferesearch/status/1645535868021805056?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1645535868021805056%7Ctwgr%5E9249fc064e87dda0be875455a1bfc43a19466712%7Ctwcon%5Es1_&amp;amp;ref_url=https%3A%2F%2Fwww.marktechpost.com%2F2023%2F04%2F14%2Fhow-does-gpt-4s-steerable-nature-set-it-apart-from-the-previous-large-language-models-llms%2F" rel="noopener noreferrer"&gt;more amenable to steerability&lt;/a&gt;. After the initial self-reinforcement training phase, it was fine-tuned via &lt;a href="https://huggingface.co/blog/rlhf" rel="noopener noreferrer"&gt;RLHF&lt;/a&gt;: Reinforcement Learning from Human Feedback.&lt;/p&gt;

&lt;p&gt;While they may seem simple, these steering phrases have proven powerful to reduce hallucination:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Stick to the facts."&lt;/li&gt;
&lt;li&gt;"It's okay to say 'I don't know.'" &lt;/li&gt;
&lt;li&gt;"Ask the user for information you may need to complete this task." &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(These seem like great advice for humans too.)&lt;/p&gt;

&lt;p&gt;Steerability is a viable strategy in the format of chat conversations as well. LangChain has a &lt;a href="https://github.com/hwchase17/langchain/blob/master/langchain/chains/conversation/prompt.py?ref=mattboegner.com" rel="noopener noreferrer"&gt;great example here&lt;/a&gt; of feeding the chat history back into the prompt with each turn to keep context fresh. Otherwise the LLM can forget context given enough further interaction, and (you guessed it) hallucinate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieval Data Augmentation &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Retrieval data augmentation involves feeding data sourced by the end user to the LLM during prompting. Sources can include APIs, private data stores (smaller amounts of data, like documents or images on your own machine), databases (for larger amounts of data), or anything found on the internet itself.&lt;/p&gt;

&lt;p&gt;I recently whipped up a React-Flask app called &lt;a href="https://github.com/aruna-x/weather-to-wear" rel="noopener noreferrer"&gt;Weather to Wear&lt;/a&gt; as a basic example of retrieval data augmentation. It queries the user for a location, calls &lt;a href="https://www.weatherapi.com/" rel="noopener noreferrer"&gt;WeatherAPI&lt;/a&gt; to get the current day's weather, then embeds the resulting data in a prompt for &lt;code&gt;gpt-3.5-turbo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn5k08d4ptemff6n0816.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn5k08d4ptemff6n0816.png" alt="Image of the Weather to Wear app, with a location autocomplete dropdown displayed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More often than not, the completion sounds reasonable:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9o73znwjxdddxrvrsi10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9o73znwjxdddxrvrsi10.png" alt="A response from GPT-3.5 recommending what to wear in Boston, MA"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the first iteration of this app, occasionally the completion included recommendations like, “Don't forget to wear sunscreen and a hat or sunglasses if necessary, as the UV index is at 1.0.” That isn't accurate. UV between 0 and 2 is considered extremely low. In fact, some experts suggest that sunscreen is unnecessary in this range.&lt;/p&gt;

&lt;p&gt;Simple fix: I augmented the prompt with a &lt;em&gt;brief&lt;/em&gt; list of uv ranges and their associated UV severities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgggyahb5lj6xl0q8ufx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgggyahb5lj6xl0q8ufx.gif" alt="GIF of the marauder's map from Harry Potter folding with an overlay title "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, this sort of simple method breaks down if we needs &lt;em&gt;lots&lt;/em&gt; of data, partially because there is a limit to the amount of data you can stuff into a prompt, &lt;a href="https://platform.openai.com/docs/models/gpt-4" rel="noopener noreferrer"&gt;depending on the model&lt;/a&gt;. Imagine a law firm that wants a custom LLM-based app, augmented with an extensive digital library of court cases. For such situations, there are more powerful ways of &lt;a href="https://mattboegner.com/knowledge-retrieval-architecture-for-llms/" rel="noopener noreferrer"&gt;architecting data retrieval augmentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's what that might look like: Because of the limits mentioned above, we'll break up the library into more manageable chunks. Next we calculate a numerical representation (a scored vector) for each chunk through a process called &lt;em&gt;embedding&lt;/em&gt;, making the information significantly more compact. Store the results.&lt;/p&gt;

&lt;p&gt;When a lawyer enters a query in search of cases related to a specific topic, we'll calculate the &lt;em&gt;query's&lt;/em&gt; embedding. Using this new query vector we search the stored results from above. Best matches will be semantically relevant to the user's query.&lt;/p&gt;

&lt;p&gt;We'll add the relevant chunks to our prompt like so:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"Document 1:" + chunk1 + "Document 2:" + chunk2 + "Document 3:" + chunk3 + ...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There's no need to build architecture like this from scratch though. Tools like &lt;a href="https://github.com/hwchase17/langchain" rel="noopener noreferrer"&gt;LangChain&lt;/a&gt; and &lt;a href="https://github.com/jerryjliu/llama_index" rel="noopener noreferrer"&gt;LlamaIndex&lt;/a&gt; have embedding features. Use them and make merry. &lt;/p&gt;

&lt;p&gt;Now our LLM can effectively have fast access to a wide store of information for augmentation purposes, without hitting the token limit for the prompt/completion or having to scour the internet on the fly. As a general rule, the more salient information we have, the better hallucinations are managed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Completion Parameters / Hyperparameters &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://platform.openai.com/docs/api-reference/completions/create" rel="noopener noreferrer"&gt;Completion parameters&lt;/a&gt; (often mistakenly called hyperparameters) are post-training inputs we can adjust via the &lt;a href="https://platform.openai.com/playground/p/default-grammar" rel="noopener noreferrer"&gt;OpenAI Playground&lt;/a&gt; or by using the &lt;a href="https://platform.openai.com/docs/guides/gpt/completions-api" rel="noopener noreferrer"&gt;OpenAI Completions API&lt;/a&gt;. (I've noticed that some SWEs include completion parameters in the prompt itself! "Temperature: 0") &lt;/p&gt;

&lt;p&gt;While we know approximately what each does, the real fun is in playing mix-and-match.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. temperature (range: 0-2, default: 1)
&lt;/h4&gt;

&lt;p&gt;Controls randomness. Low values are more deterministic. Use high values to get whacky.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. top_p (range: 0-1, default: 1)
&lt;/h4&gt;

&lt;p&gt;Also called nucleus sampling. Controls the pool of results from which a completion can be created. When top_p = 0.1, the model considers only the top 10% of the probability mass of tokens.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: OpenAI docs suggest using either temperature or top_p but not both. However, engineers working for OpenAI say to have at it. Press all the buttons.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. presence_penalty (range: -2 to 2, default: 0)
&lt;/h4&gt;

&lt;p&gt;Adjusts the bias of the model to choose novel tokens. Low values allow repeated tokens. High values encourage token novelty in the completion (in both diction and subject matter). This is a one-time adjustment applied to all tokens used at least once.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. frequency_penalty (range: -2 to 2, default: 0)
&lt;/h4&gt;

&lt;p&gt;Adjusts the bias of the model to limit token repetition in proportion to each token's frequency. Low values allow for more repetition. High values penalize repetition.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: On the surface presence and frequency penalties might look similar. They are not. Presence is a one-time adjustment applied to all tokens. Frequency is proportionally applied to each and every token.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  5. logit bias (range: -100 to 100, requires: JSON object mapping specific tokens)
&lt;/h4&gt;

&lt;p&gt;Controls the likelihood of tokens appearing in the completion at all. Use token IDs to specify which token likelihoods to modify. (e.g. {"31373": -100} will ensure that 'hello' will not appear.)&lt;/p&gt;

&lt;p&gt;Assessing steerability vs fine-tuning with completion parameters feels like taking a lateral walk through language itself. With so many variables, exploring this space is equal parts compelling and confusing. But also, completely fun.&lt;/p&gt;

&lt;p&gt;But for the purposes of limiting LLM hallucinations, the trick is to find the sweet spot where the completions are predictable enough to sound sane, but unpredictable enough to sound unlike a machine (if that's what you're after).&lt;/p&gt;

&lt;h3&gt;
  
  
  Chain-of-Thought (CoT) Prompting &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ai.googleblog.com/2022/05/language-models-perform-reasoning-via.html" rel="noopener noreferrer"&gt;Chain-of-thought prompting&lt;/a&gt; extends the concept of few-shot prompting to enable the LLM to model a certain flavor of reasoning, as in sufficiently complex math problems. It's also useful when we want output to conform to a specified format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One-shot prompting:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"This is wonderful!" &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm glad to hear that you're enjoying our conversation! I'm here to help and provide information to the best of my abilities. If there's anything specific you'd like to discuss or any questions you have, feel free to let me know. I'm here to assist you!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aww, wholesome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Few-shot prompting:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What if we wanted ChatGPT to indicate whether the sentence was positive or negative in tone? Let's feed it some formatted examples with &lt;a href="https://www.promptingguide.ai/techniques/fewshot" rel="noopener noreferrer"&gt;few-shot&lt;/a&gt; prompting.&lt;/p&gt;

&lt;p&gt;"This is awesome! // Negative&lt;br&gt;
This is bad! // Positive&lt;br&gt;
Wow that movie was rad! // Positive&lt;br&gt;
What a horrible show! // "&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Negative&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For more complicated tasks we'll need to expose the LLM to intermediate steps of reasoning (a &lt;em&gt;chain-of-thought&lt;/em&gt; if you will). Note that chain-of-thought prompting works especially well for 100+ billion parameter models. Also, ChatGPT has already evolved enough to automatically achieve and share CoT on its own for a variety of tasks. Basic uses of this strategy may become obsolete soon.&lt;/p&gt;

&lt;p&gt;In some cases, you can approximate CoT prompting simply by adding this to your prompt: "Let's think step-by-step." Or, even better: "State each step and then show your work for performing that step." According to &lt;em&gt;stevenic&lt;/em&gt; on the OpenAI forum, the latter phrasing improved hallucinations significantly, when used at the end of his prompts.&lt;/p&gt;

&lt;p&gt;Here's a toy example of CoT prompting offered by &lt;a href="https://ai.googleblog.com/2022/05/language-models-perform-reasoning-via.html" rel="noopener noreferrer"&gt;this Google research article&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figd0v5ta37c1gr1vug8b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figd0v5ta37c1gr1vug8b.png" alt="Toy example of chain-of-thought prompting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're anything like me, you don't find toy examples satisfying. Besides, this example (and most of the others I can find online) are already obsolete. ChatGPT definitely exposes reasoning in response to the standard prompt above.&lt;/p&gt;

&lt;p&gt;I recommend reading &lt;a href="https://community.openai.com/t/a-better-chain-of-thought-prompt/128180" rel="noopener noreferrer"&gt;this thread on the OpenAI forum&lt;/a&gt;, in which &lt;em&gt;stevenic&lt;/em&gt; shares how he crafted a prompt that taught GPT-4 how to play risk with a human user. This thread has further discussion about his CoT format: &lt;a href="https://community.openai.com/t/building-hallucination-resistant-prompts/131036/2" rel="noopener noreferrer"&gt;Building Hallucination Resistant Prompts&lt;/a&gt;. It's the most compelling example of chain-of-thought prompting I've been able to find. Seriously, Steve has a fan over here.&lt;/p&gt;




&lt;p&gt;I would love to hear your thoughts on LLM hallucinations in the comments. What strategies have you found most effective?&lt;/p&gt;

&lt;p&gt;Stay tuned for my next project: a static single-page React chat app incorporating ChatGPT and information on my professional background, for my portfolio site. A user should be able to dictate the chat entity's personality and professional demeanor. Who says work can't be fun?&lt;/p&gt;




&lt;p&gt;Addendum: for creatives and the curious in the mood to lean in to the hallucinations, try &lt;a href="https://github.com/DivergentAI/dreamGPT" rel="noopener noreferrer"&gt;DreamGPT&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cover &lt;a href="https://unsplash.com/photos/gakXaqzGad0?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;image&lt;/a&gt; by &lt;a href="https://unsplash.com/@steve_j?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Steve Johnson&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>chatgpt</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>The Wacky World of Closures &amp; What Makes Them Useful</title>
      <dc:creator>aruna-x</dc:creator>
      <pubDate>Thu, 16 Dec 2021 02:18:43 +0000</pubDate>
      <link>https://dev.to/aruna/the-wacky-world-of-closures-what-makes-them-useful-24a7</link>
      <guid>https://dev.to/aruna/the-wacky-world-of-closures-what-makes-them-useful-24a7</guid>
      <description>&lt;p&gt;Can you guess what this prints out?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... Are you sure? There's a gotcha here, and if you're not aware of it already, I'd wager this blog post is worth your time. &lt;em&gt;(Hint: 0, 1, 2 is incorrect.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Closure With Javascript
&lt;/h2&gt;

&lt;p&gt;To understand what's happening in the above code snippet, we have to understand closures. If you're looking for practical applications of closures, you can jump ahead.&lt;/p&gt;

&lt;p&gt;A closure has a surprisingly simple definition: a function with access to &lt;em&gt;information outside of itself&lt;/em&gt;, otherwise known as its "lexical environment". &lt;code&gt;function addTwo()&lt;/code&gt; is a closure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addTwo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;let x = 5&lt;/code&gt; is in its lexical environment.&lt;/p&gt;

&lt;p&gt;All functions in Javascript can be closures, because they automatically gain access to outer scope.&lt;/p&gt;

&lt;p&gt;By contrast, pure functions are not closures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addNums&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;addNums&lt;/code&gt; does not reference any data outside of its own scope. Its data is kept in your computer's short term memory. It gets pushed onto the "call stack", executed, and then popped off the stack again. Clean, simple, easy. &lt;/p&gt;

&lt;p&gt;On the other hand, when a function references information outside of its own scope (as with a closure), its data becomes packaged (or "enclosed") with references to all of its lexical info, and the entire package gets placed in longer term memory, called the heap. We can thank a memory management process called &lt;a href="https://javascript.info/garbage-collection"&gt;garbage collection&lt;/a&gt; for keeping the heap clear of information we no longer need in long term memory.&lt;/p&gt;

&lt;p&gt;Despite closures needing more memory and computational power, there are some great reasons to use them (which I'll cover in a moment below).&lt;/p&gt;

&lt;h2&gt;
  
  
  Not All Closures Are Made The Same
&lt;/h2&gt;

&lt;p&gt;Closures are particularly easy in Javascript.&lt;/p&gt;

&lt;p&gt;You can use &lt;a href="https://letoverlambda.com/"&gt;&lt;em&gt;let over lambda&lt;/em&gt;&lt;/a&gt; to create a closure in &lt;a href="https://en.wikipedia.org/wiki/Lisp_(programming_language)"&gt;Lisp&lt;/a&gt; (the second oldest higher-level programming language). &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;nonlocal&lt;/code&gt; keyword is helpful to gain access to variables normally outside of scope in &lt;a href="https://zetcode.com/python/python-closures/"&gt;python closures&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In C# however, &lt;a href="https://www.simplethread.com/c-closures-explained/"&gt;closures&lt;/a&gt; must explicitly be &lt;em&gt;enclosed&lt;/em&gt; with its lexical environment, through "binding" variables.&lt;/p&gt;

&lt;p&gt;You get the idea. For now, we'll continue to use Javascript.&lt;br&gt;
&lt;span id="uses"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What Makes Closures Uniquely Useful?
&lt;/h2&gt;

&lt;p&gt;There is surprisingly sparse info online about &lt;em&gt;uses&lt;/em&gt; for closures. It's odd! While I'm sure there are many more uses, there seem to be at least two compelling ones I'd like to discuss:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function factories&lt;/li&gt;
&lt;li&gt;Namespacing private functions&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Function Factories
&lt;/h3&gt;

&lt;p&gt;Function factories are functions that return other functions based on various conditions. I'd like to share how I used a function factory in a recent project. But first, let's look at a simple example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
      &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we call &lt;code&gt;factory(5)&lt;/code&gt;, it returns &lt;code&gt;(b) =&amp;gt; 5 % b&lt;/code&gt;. &lt;br&gt;
If we call &lt;code&gt;factory(4)&lt;/code&gt; it returns &lt;code&gt;(b) =&amp;gt; 4 + b&lt;/code&gt;. &lt;br&gt;
And if we call &lt;code&gt;factory(4)(2)&lt;/code&gt; we can see that:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;factory(4) = (b) =&amp;gt; 4 + b&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;factory(4)(2)&lt;/code&gt; becomes &lt;code&gt;((b) =&amp;gt; 4 + b)(2)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Resulting in &lt;code&gt;(2) =&amp;gt; 4 + 2&lt;/code&gt;. Which returns &lt;code&gt;6&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The important note here is that function factories return &lt;em&gt;functions&lt;/em&gt; that can accept even more info.&lt;/p&gt;
&lt;h4&gt;
  
  
  A Closure Function Factory In Use
&lt;/h4&gt;

&lt;p&gt;I recently built a notes app with a react front end using &lt;code&gt;semantic-ui-react&lt;/code&gt;. The new note form included a dropdown menu. (Bear with me here.) &lt;/p&gt;

&lt;p&gt;&lt;code&gt;semantic-ui-react&lt;/code&gt;'s dropdown menu requires an array of &lt;code&gt;options&lt;/code&gt;. Once I fetched data from my database and generated the options array, it looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can feed this array to the dropdown like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Dropdown&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropdown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;multiple&lt;/span&gt;
    &lt;span class="nx"&gt;search&lt;/span&gt;
    &lt;span class="nx"&gt;selection&lt;/span&gt;
    &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(I've simplified all of these snippets of code for readability.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This dropdown will allow you to make multiple selections. It turns out the &lt;code&gt;value&lt;/code&gt; attribute of &lt;code&gt;semanitic-ui-react&lt;/code&gt;'s dropdown menu is an array of &lt;code&gt;value&lt;/code&gt;s from the objects in &lt;code&gt;options&lt;/code&gt;. I wanted to store whole objects from &lt;code&gt;options&lt;/code&gt; in state instead. &lt;/p&gt;

&lt;p&gt;I wanted just one change handler function for all form elements. Closure to the rescue.&lt;/p&gt;

&lt;p&gt;Every form element executes the same function on change, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;handleMaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"name" matches the name attribute of the form element it's associated with for style reasons.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;handleMaker&lt;/code&gt; is a function factory that returns a &lt;em&gt;different&lt;/em&gt; function based on which form element name is passed in. The function &lt;em&gt;returned&lt;/em&gt; from &lt;code&gt;handleMaker&lt;/code&gt; accepts the onChange event as an argument.&lt;/p&gt;

&lt;p&gt;Here is a simplified version of the function factory I use in the app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleMaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;note&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setFormData&lt;/span&gt;&lt;span class="p"&gt;({...&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;collections&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setFormData&lt;/span&gt;&lt;span class="p"&gt;({...&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropdown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setFormData&lt;/span&gt;&lt;span class="p"&gt;({...&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})})&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Oops, something went wrong!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are other cases here, showing how a function factory can help handle all sorts of special cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Namespacing private functions
&lt;/h3&gt;

&lt;p&gt;Private functions make apps more secure, disallowing ill-intentioned users from calling functions or methods that can mutate the app's state unhelpfully (or, in some cases, even inject code). &lt;/p&gt;

&lt;p&gt;Ruby has a &lt;code&gt;private&lt;/code&gt; keyword to make methods private. Javascript didn't &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields"&gt;until recently&lt;/a&gt;. But that applies to classes. When we're not inside classes (or running on IE, lol), we can still &lt;a href="https://www.oreilly.com/library/view/learning-javascript-design/9781449334840/ch13s15.html"&gt;namespace private javascript functions&lt;/a&gt; with closures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;namespacer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;changer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;public1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;changer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;public2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;changer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;public3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;})()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we can see that namespacer is actually an object with closures as keys, since the anonymous function on line 1 is immediately invoked on the last line. &lt;/p&gt;

&lt;p&gt;We can call the public functions like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;namespacer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 200&lt;/span&gt;
&lt;span class="nx"&gt;namespacer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 100&lt;/span&gt;
&lt;span class="nx"&gt;namespacer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public3&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we would be unable to call &lt;code&gt;changer&lt;/code&gt; directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;namespacer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;changer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: undefined is not a function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or access &lt;code&gt;num&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;namespacer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Presto! Private functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closures In Interviews
&lt;/h2&gt;

&lt;p&gt;If you are new to web dev and preparing for interviews, it may interest you to know that there is a common interview question involving closures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can you guess what &lt;code&gt;console.log&lt;/code&gt;s here?&lt;/p&gt;

&lt;p&gt;If you guessed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... you'd be right! We might expect 0, 1, 2 but that won't happen here. Each time we go through the loop, &lt;code&gt;setTimeout&lt;/code&gt; waits a whole 2 seconds before running. The &lt;code&gt;i&lt;/code&gt; inside of the &lt;code&gt;setTimeout&lt;/code&gt; callback function refers to the &lt;code&gt;i&lt;/code&gt; from the loop. Instantiating it with &lt;code&gt;var&lt;/code&gt; gives us access to that variable even after it's done running. In 2 seconds, the loop will have run 4 times. Once &lt;code&gt;i&lt;/code&gt; is assigned 3, it fails the condition and exits the for loop, leaving &lt;code&gt;i&lt;/code&gt; at 3 when all three &lt;code&gt;setTimeout&lt;/code&gt;s eventually run.&lt;/p&gt;

&lt;p&gt;There are a number of ways we can fix this. One way is to wrap the callback function inside of &lt;code&gt;setTimeout&lt;/code&gt; in an immediately invoked function that accepts &lt;code&gt;i&lt;/code&gt; as its argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)))(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does this accomplish? Wrapping the callback function in an immediately invoked function ensures that the current value of &lt;code&gt;i&lt;/code&gt; is passed in and kept in the state of the &lt;code&gt;setTimeout&lt;/code&gt; function. It is stored there for later use.&lt;/p&gt;

&lt;p&gt;Another way we can do this involves wrapping the entirety of the &lt;code&gt;setTimeout&lt;/code&gt; in the same immediately invoked function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;))(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This accomplishes the same result.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Final Musing:
&lt;/h2&gt;

&lt;p&gt;I'm curious to know whether there is a language in which creating a closure is impossible. So far my Googling efforts haven't gotten me far. I'd be grateful for your thoughts on the topic.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Abstract Syntax Trees: They're Actually Used Everywhere -- But What Are They?</title>
      <dc:creator>aruna-x</dc:creator>
      <pubDate>Wed, 17 Nov 2021 21:02:00 +0000</pubDate>
      <link>https://dev.to/aruna/abstract-syntax-trees-theyre-used-everywhere-but-what-are-they-jh6</link>
      <guid>https://dev.to/aruna/abstract-syntax-trees-theyre-used-everywhere-but-what-are-they-jh6</guid>
      <description>&lt;p&gt;Isn't it wonderful how &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt; grays out obsolete lines of code? &lt;em&gt;Oops, my return statement is on line 3. Line 4 won't run...&lt;/em&gt; But I haven't called the function yet. So how in the world does VS Code know which lines of code won't be used in the future, when the code finally does run?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn37rbnd7xpc7iyf3kcxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn37rbnd7xpc7iyf3kcxx.png" alt="Code snippet of a function in VS Code with line 4 grayed out"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we have a conditional statement, VS Code accurately evaluates the potential for us to hit the code outside of it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nmqkgsugr8stdumtd9v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nmqkgsugr8stdumtd9v.png" alt="Code snippet showing that VS Code knows that an if statement with an unknown conditional might not run"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bool&lt;/code&gt; could turn out to be false after all. But if we change the condition to &lt;code&gt;true&lt;/code&gt; VS Code knows we will &lt;em&gt;always&lt;/em&gt; run that block and (if there is an inevitable return inside) never reach the final line:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczrc9sgdf3ibbmgz9pxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczrc9sgdf3ibbmgz9pxl.png" alt="Code snippet showing that VS Code knows that an if statement with a true conditional will always run"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's almost as if VS Code has the ability to understand the &lt;em&gt;semantics&lt;/em&gt; of code. But under the hood VS Code uses &lt;strong&gt;code&lt;/strong&gt; to do this! How?&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter: Abstract Syntax Trees (ASTs)
&lt;/h2&gt;

&lt;p&gt;An AST is a data structure that encodes abstract information about a piece of code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99b0l2z3twokjltcegwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99b0l2z3twokjltcegwa.png" alt="an AST object of the above code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This one is specifically for the above sample code declaring &lt;code&gt;function foo(bool)&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An AST is a "tree", which is a kind of graph. And a graph is a very useful type of data structure, ubiquitous in software engineering. In order to understand ASTs we have to understand graphs. &lt;em&gt;(You can also skip ahead to learn more about ASTs or look at these tools to make and use an AST yourself.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do Graphs Work?
&lt;/h2&gt;

&lt;p&gt;Graphs consist of "nodes" and "edges", and can be represented by (often nested) objects or arrays. A graph can mix objects and arrays as well, nesting one kind within the other to whatever degree of complexity.&lt;/p&gt;

&lt;p&gt;Each node and edge can contain information. You can travel from one node to another via the edge between them. Edges have direction as well. Here's a simple graph connecting node A to node B:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmek3jl2ome6q4u6di4w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmek3jl2ome6q4u6di4w.png" alt="Simple graph showing A to B"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At a very basic level, if you were to write this in Javascript, it could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ["A", ["B"] ], [ "B", [] ] ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ 
   A: { value: data_set1, children: ["B"] }, 
   B: { value: data_set2, children: [] }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can flip the direction&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8h2ybtaok1zyly9arp8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8h2ybtaok1zyly9arp8g.png" alt="Simple graph showing B to A"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Resulting in code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ["A", [] ], [ "B", ["A"] ] ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ 
   A: { value: data_set1, children: [] }, 
   B: { value: data_set2, children: ["A"] }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you can make the edge bidirectional, usually represented with a plain line with no arrows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyfw9nvrc10ygznonowq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyfw9nvrc10ygznonowq.png" alt="Simple graph showing a bidirectional relationship between A and B"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With code that does something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ["A", ["B"] ], [ "B", ["A"] ] ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ 
   A: { value: data_set1, children: ["B"] }, 
   B: { value: data_set2, children: ["A"] }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are simple examples, and in practice graphs can encode large amounts of data. Google displays search results with the help of a &lt;a href="https://en.wikipedia.org/wiki/PageRank" rel="noopener noreferrer"&gt;page rank&lt;/a&gt; graph, for example. This is a simplified representation of one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9hqfj7k3f4cw6dt6x3u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9hqfj7k3f4cw6dt6x3u.png" alt="Simplified rank graph example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Graphs can also have certain constraints. We can say: "The graph will start with exactly one node and every node except the first will have exactly one parent. Nodes can have multiple children though."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4gzvq8vsglgz9d5yw0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4gzvq8vsglgz9d5yw0q.png" alt="image of a tree data structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is an example of one kind of tree. In general, a tree branches out. Every node after the first (root node) has exactly one parent. Trees are hierarchical and do not contain loops. &lt;em&gt;(Graphs can have loops, and do not necessarily have a root node.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But for now we'll focus on trees. Because when we build an AST, we take abstract syntactical data from code and encode it into a tree.&lt;br&gt;
&lt;span id="ASTs"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  AST Design Standards &amp;amp; Traversal Functions
&lt;/h2&gt;

&lt;p&gt;Because ASTs are often used in the process of compiling code (which happens &lt;em&gt;all&lt;/em&gt; the time - every time you try to run &lt;em&gt;any&lt;/em&gt; code), AST design standards are fairly robust. Compilers (and interpreters) essentially take the code we write (in Javascript, Python, Ruby, or C++) and turn it into machine-language instructions that a computer's CPU can run.&lt;/p&gt;

&lt;p&gt;AST design standards include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;variables (and their declaration locations in the source code) must be preserved&lt;/li&gt;
&lt;li&gt;the order in which statements get executed is well defined and preserved&lt;/li&gt;
&lt;li&gt;in the case of binary operations, left and right positioning is preserved&lt;/li&gt;
&lt;li&gt;identifiers and their values are stored&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ultimately, broken code cannot be turned into an AST. In the process of building the AST, we might come across errors like missing brackets, untyped variables (as in Typescript), or other syntactic mistakes. Instead of proceeding, we can flag these errors and display them to users for correction.&lt;/p&gt;

&lt;p&gt;But once we successfully build an AST, it should be possible to &lt;em&gt;unparse&lt;/em&gt; an it into something very similar to the original code, using a code generator. And the resulting code should definitely &lt;em&gt;function&lt;/em&gt; exactly the same as the original code.&lt;/p&gt;

&lt;p&gt;For example, using an AST like this ...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuqij99vqzf9ww5193cks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuqij99vqzf9ww5193cks.png" alt="representation of generalized AST as graph showing the kinds of information each node and edge contain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We could rebuild code that would look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function euclid(a,b) {
   while (b !== 0) {
      if (a &amp;gt; b) { a = a - b; } 
      else { b = b - a; }
   } 
   return a;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we can take a piece of code, turn it into an AST, and eventually turn that back into code. But wait ... there's more: The function we use to step through the AST (called an AST traversal function) is intelligent enough to make sense of the semantic encodings and help us do useful things with that information. &lt;/p&gt;

&lt;p&gt;We can use an AST traversal function to walk along the structure to discover "dead branches" (pieces of code that will never run).&lt;/p&gt;

&lt;h2&gt;
  
  
  Tree Shaking &amp;amp; More
&lt;/h2&gt;

&lt;p&gt;Tree shaking refers to dead-code elimination in Javascript. In order to tree shake, we would combine the use of an AST and an AST traversal function to find which "branches" of code are "dead". This is how VS Code grays out unused lines of code. Tree shaking then eliminates those unused lines of code, for a cleaner, leaner code base.&lt;/p&gt;

&lt;p&gt;When a code base is sufficiently large, dead-code elimination is necessary. Dead ends become dead weight, potentially causing worse performance if the product is shipped and bloated code in much need of pruning. &lt;em&gt;(Amusingly, that's not a pun. That's what they call it! I came across many articles on tree pruning in writing this post though.)&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;There's incentive on both ends, as &lt;em&gt;wet&lt;/em&gt; code is more confusing for developers as well.&lt;/p&gt;

&lt;p&gt;The same traversal function can, interestingly, help us inject our own code into a given chunk of code according to preset rules if we wanted. (More about this in the follow up below.)&lt;br&gt;
&lt;span id="tools"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools To Make And Use An AST
&lt;/h2&gt;

&lt;p&gt;Create an AST: &lt;a href="https://esprima.org/" rel="noopener noreferrer"&gt;Esprima&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Traverse that AST and replace or inject code: &lt;a href="https://github.com/estools/estraverse" rel="noopener noreferrer"&gt;Extraverse&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unparse the modified AST back into Javascript: &lt;a href="https://github.com/estools/escodegen" rel="noopener noreferrer"&gt;Escodegen&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ASTs vs CPTs
&lt;/h2&gt;

&lt;p&gt;I mentioned earlier that ASTs are used in the process of compiling or interpreting. There is an alternative: Concrete Parse Tree. Unlike ASTs, CPTs include much more granular (potentially unnecessary) information. ASTs can omit some syntactic information like grouping parentheses, because of the way in which the structure of an AST already encodes that information. &lt;/p&gt;

&lt;p&gt;CSTs are much bigger than ASTs. But the tradeoff is that they can aid in more &lt;em&gt;efficient&lt;/em&gt; compiling. In practice, both are used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow Up
&lt;/h2&gt;

&lt;p&gt;My fascination with ASTs was inspired by an app I'm working on: a Big O (time complexity) calculator.&lt;/p&gt;

&lt;p&gt;In my research on Big O approximation, I found that most tools calculate the &lt;strong&gt;amount of time&lt;/strong&gt; a machine takes to run a function on different sized data sets. They use the resulting amounts of time to determine whether the rate of growth of time is sublinear, linear, exponential, etc.&lt;/p&gt;

&lt;p&gt;I hope to create a tool that will count the &lt;strong&gt;number of actions&lt;/strong&gt; taken (rather than the amount of time for a specific machine), so that for any snippet of code I can point to the most costly lines and indicate how many times they ran. This can help students learn Big O with a more concrete understanding of what's happening with their code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Halting Problem
&lt;/h3&gt;

&lt;p&gt;Slightly outside the scope of this article, but cool enough to include: In 1936, Alan Turing (pictured at age 16, below) proved that it is impossible to write code that can examine another piece of code and its input, and tell whether or not it will ever terminate. This is called the &lt;a href="https://en.wikipedia.org/wiki/Halting_problem" rel="noopener noreferrer"&gt;halting problem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fve3gu6l2mnpib5gsobex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fve3gu6l2mnpib5gsobex.png" alt="Alan Turing, age 16"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this reason, code entered into the Big O calculator can run too long in an infinite loop, and lock up a user's computer. I plan to bake in a fail-safe for that.&lt;/p&gt;

&lt;h3&gt;
  
  
  We'll See What's Possible
&lt;/h3&gt;

&lt;p&gt;I'd eventually like to expand the project into a more comprehensive teaching tool. For now, I've scoped the project to the calculator to see if it's viable.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vscode</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>String Matching Algorithm Uses, Interactive Implementations, &amp; Free Source Code</title>
      <dc:creator>aruna-x</dc:creator>
      <pubDate>Thu, 04 Nov 2021 06:30:28 +0000</pubDate>
      <link>https://dev.to/aruna/string-matching-algorithm-uses-interactive-implementation-free-source-code-393</link>
      <guid>https://dev.to/aruna/string-matching-algorithm-uses-interactive-implementation-free-source-code-393</guid>
      <description>&lt;p&gt;Ahhh autocorrect. How many times has it changed a four-letter expletive to "duck"? Though when autocorrect works as planned, it enables us to have smoother, more intuitive experiences with technology rather than hindering our free expression. At the heart of autocorrect is a well-intentioned &lt;strong&gt;string matching algorithm&lt;/strong&gt;. There are many such tools, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;username and password hash matching&lt;/li&gt;
&lt;li&gt;search engines&lt;/li&gt;
&lt;li&gt;autocorrect&lt;/li&gt;
&lt;li&gt;spell checkers&lt;/li&gt;
&lt;li&gt;email spam filters&lt;/li&gt;
&lt;li&gt;plagiarism detection software&lt;/li&gt;
&lt;li&gt;bioinformatics and DNA sequencing tools&lt;/li&gt;
&lt;li&gt;quiz games!&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Exact String Matching
&lt;/h1&gt;

&lt;p&gt;There are two types of string matching: exact and fuzzy. &lt;strong&gt;Exact string matching&lt;/strong&gt; is precisely as it sounds. Only identical strings pass the test, so to speak.&lt;/p&gt;

&lt;p&gt;Something similar to this simple implementation seems useful for username and password hash matching. (Note: I've made this case sensitive for simplicity.)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Click the green play button to run this code. To edit code, create a replit account, fork this code, and have at it.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@arunax/Exact-String-Matching-Whole-Word?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;em&gt;After pressing the green play button, you can feed the function your own strings in this console! Try entering: isExactMatch("string", "ring")&lt;/em&gt;&lt;br&gt;
&lt;br&gt;

&lt;p&gt;But perhaps we don't want to match &lt;em&gt;whole&lt;/em&gt; strings. If we wanted to search large data for some exact substring query, we could redefine our criteria: exact &lt;strong&gt;common substring&lt;/strong&gt; matches of length 4 or more found anywhere within either string, let's say. Then "apple" and "grappled" would pass. &lt;/p&gt;

&lt;p&gt;The below implementation is called &lt;strong&gt;Longest Common Substring&lt;/strong&gt;. Let's make it case insensitive. And if you've found this blog looking for a version that won't just check the first n characters (mystifyingly abundant online), but will return a match for any substring found anywhere &lt;em&gt;within&lt;/em&gt; either string (way more useful imho), you're in luck:&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@arunax/Exact-String-Matching-Common-Substring?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Replace "4" on line 4 in the expression "end - beg &amp;gt; 4" with any number that allows your test data to succeed robustly.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Common substring has its limitations. For example, it fails "receipt vs reciept", a common typo. We'll circle back to this a bit later in this article.&lt;/p&gt;

&lt;p&gt;There are indeed more powerful algorithms like the &lt;a href="https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm" rel="noopener noreferrer"&gt;Boyer–Moore string-search algorithm&lt;/a&gt;, which avoids searching strings one character at a time. Instead, to increase efficiency, it explores the string being searched by jumping past ranges of characters and performs tail-first matching on the query string itself (which is assumed to be shorter). Fancy.&lt;/p&gt;

&lt;p&gt;There's also the &lt;a href="https://blog.jcoglan.com/2017/02/12/the-myers-diff-algorithm-part-1/" rel="noopener noreferrer"&gt;Meyers diff algorithm&lt;/a&gt;, used to highlight diffs in Github!&lt;/p&gt;

&lt;p&gt;But for now, we'll move on to fuzzy string matching. Maybe I'll circle back to follow up on the Boyer–Moore string-search algorithm and the Meyer's diff algorithm in future updates.&lt;/p&gt;

&lt;h1&gt;
  
  
  Fuzzy String Matching
&lt;/h1&gt;

&lt;p&gt;Google search queries often include typos. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9dh4dyoyxpjfa8kenmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9dh4dyoyxpjfa8kenmw.png" alt="Google search for cheesecake demonstrating google's autocorrect"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Autocorrect can helpfully suggest adding back the "f" in "shift" in a work email. Bioinformatics tools can find gene mutations by detecting slight changes from original sequences. And spam filters can catch variations of common red flag phrases, despite spammers' best attempts at obfuscation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fuzzy string matching&lt;/strong&gt; does some heavy lifting here. With fuzzy string matching (also referred to as &lt;strong&gt;inexact string matching&lt;/strong&gt; or &lt;strong&gt;approximate string matching&lt;/strong&gt;) we can probabilistically and algorithmically find most &lt;em&gt;likely&lt;/em&gt; matches.&lt;/p&gt;

&lt;p&gt;Here I've chosen to implement &lt;a href="https://en.wikipedia.org/wiki/Levenshtein_distance" rel="noopener noreferrer"&gt;Levenshtein distance&lt;/a&gt;, the most common example of &lt;a href="https://en.wikipedia.org/wiki/Edit_distance" rel="noopener noreferrer"&gt;Edit distance&lt;/a&gt;. People often use these terms interchangeably, though there are other Edit distances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Levenshtein Distance&lt;/strong&gt; is in essence quite simple. It represents the &lt;em&gt;minimum&lt;/em&gt; number of &lt;strong&gt;insertions&lt;/strong&gt;, &lt;strong&gt;deletions&lt;/strong&gt;, and &lt;strong&gt;substitutions&lt;/strong&gt; it takes to make one string match another. To calculate the distance we use a matrix encoded with all possible operations on all possible substrings starting from the beginnings. This allows us to find and use the minimums on each operation dynamically.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This implementation uses a threshold of &amp;lt; 3. You can change that on line 25 after forking or copying.&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@arunax/Fuzzy-String-Matching-Levenshtein-Distance?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;


&lt;p&gt;According to my research, Levenshtein distance is considered the gold standard for fuzzy string matching. It hasn't been improved in about 50 years. For a comprehensive explanation, I highly recommend &lt;a href="https://medium.com/@ethannam/understanding-the-levenshtein-distance-equation-for-beginners-c4285a5604f0" rel="noopener noreferrer"&gt;Understanding the Levenshtein Distance Equation for Beginners&lt;/a&gt; by Ethan Nam.&lt;/p&gt;

&lt;p&gt;Even given its cachet, Levenshtein distance also has limitations. Unlike common substring it will pass "receipt vs reciept", but it will fail "Mt Whitney vs Mount Whitney" which common substring handles beautifully. Let's talk about that below.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;A few weeks ago I co-created a kawaii-style quiz game called &lt;a href="https://aruna-x.github.io/cookie-monster-in-jeopardy/" rel="noopener noreferrer"&gt;"Cookie-Loving Monster In Danger!"&lt;/a&gt; that uses the tech mentioned above. &lt;em&gt;(No affiliation with Sesame Street or Jeopardy!)&lt;/em&gt; In order to get a functional version of string matching, I used &lt;em&gt;all&lt;/em&gt; of these: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;removal of special characters using regex&lt;/li&gt;
&lt;li&gt;some simple logic to handle the edge case of query strings less than 3 characters&lt;/li&gt;
&lt;li&gt;longest common substring (at a threshold of &amp;gt;4)&lt;/li&gt;
&lt;li&gt;Levenshtein distance (at a threshold of &amp;lt;3)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the final code. Try running it to see the test output, then test your own cases using the format stringAnalysis("string1", "string2"):&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@arunax/String-Matching-Final-Analysis?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;


&lt;p&gt;There are ways in which the above fails. It doesn't work with absolute accuracy.&lt;/p&gt;

&lt;p&gt;However, this code worked well enough to make &lt;a href="https://aruna-x.github.io/cookie-monster-in-jeopardy/" rel="noopener noreferrer"&gt;"Cookie-Loving Monster In Danger!"&lt;/a&gt; playable. So if you're curious to see it in action, hop over and play a game. If you win, there's a fun surprise in store. Or you can watch my walkthrough video &lt;a href="https://vimeo.com/manage/videos/670021116/8d9ee7485e" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Follow Up
&lt;/h1&gt;

&lt;p&gt;In the future, I'd be interested in creating my own implementations of the Boyer–Moore string-search algorithm and the Meyers diff algorithm, as I did with all of the above code snippets. I'd also be interested in improving the final code snippet by refactoring and further optimizing time and space complexity. I'd include a dictionary of common reasonable substitutions (like "2" and "two"). Then I'd take into account the probability of the occurrence of letters, common misspellings, and words in &lt;em&gt;context&lt;/em&gt; (given actual usage).&lt;/p&gt;

&lt;p&gt;Inspiration for the latter of these improvements comes from &lt;a href="https://norvig.com/spell-correct.html" rel="noopener noreferrer"&gt;How to Write a Spelling Corrector&lt;/a&gt; by Peter Norvig. Well worth the read.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>algorithms</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
