<?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: Rajiv Abraham</title>
    <description>The latest articles on DEV Community by Rajiv Abraham (@rabraham).</description>
    <link>https://dev.to/rabraham</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%2F278332%2F7db4c257-73f2-4736-a29a-22513ebfb406.jpeg</url>
      <title>DEV Community: Rajiv Abraham</title>
      <link>https://dev.to/rabraham</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rabraham"/>
    <language>en</language>
    <item>
      <title>Personal Experience: Software Engineer Job Search in Canada during COVID-19: Apr 9th - June 1st(53 days)</title>
      <dc:creator>Rajiv Abraham</dc:creator>
      <pubDate>Sun, 31 May 2020 19:26:43 +0000</pubDate>
      <link>https://dev.to/rabraham/personal-experience-software-engineer-job-search-in-canada-during-covid-19-apr-9th-june-1st-53-days-495m</link>
      <guid>https://dev.to/rabraham/personal-experience-software-engineer-job-search-in-canada-during-covid-19-apr-9th-june-1st-53-days-495m</guid>
      <description>&lt;p&gt;This article was originally posted at &lt;code&gt;https://blog.rajivabraham.com/posts/job-search-2020&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Purpose.
&lt;/h1&gt;

&lt;p&gt;This article is about sharing my job search experience in case it's interesting or useful to anyone. &lt;/p&gt;

&lt;h1&gt;
  
  
  About me
&lt;/h1&gt;

&lt;p&gt;I had decided to come back to a full time job after more than a year at my startup 15Rock. I have been developing professionally for 12 years now. Though twelve years is a big number, opportunities and circumstances, made me a generalist instead of a specialist i.e. I had maximum two years experience in any technology that I had worked on. So, I never fully fit the &lt;code&gt;Senior/Architect Java/Ruby/Python&lt;/code&gt; profiles where companies expected in depth knowledge of technologies.&lt;/p&gt;

&lt;p&gt;Also, in my free time, I like exploring concepts(Functional Programming, Logic Programming) which I believe are significant levers of productivity and developing my own libraries(&lt;a href="https://github.com/RAbraham/mercylog"&gt;Mercylog&lt;/a&gt;, &lt;a href="https://thampi.readthedocs.io/en/latest/"&gt;Thampi&lt;/a&gt;, &lt;a href="https://github.com/RAbraham/jaya"&gt;Jaya&lt;/a&gt;) when I could have spent that time, perhaps, learning current industry standards like Apache Spark, Deep Learning, Tensorflow or explored SQL in depth. &lt;/p&gt;

&lt;h1&gt;
  
  
  Job Search Strategy
&lt;/h1&gt;

&lt;p&gt;I was applying for Machine Learning and Data Engineer roles as that was my recent experience and I'm really excited to apply all the software engineering processes that I obsess about(Yes, TDD ;) ) to the field of machine learning and data engineering. I had around 6 months of machine learning engineering knowledge and 2.5 years in data engineering in Python.&lt;/p&gt;

&lt;h1&gt;
  
  
  Hiring Environment
&lt;/h1&gt;

&lt;p&gt;I was having lunch with an ex co-worker who was working in an interesting company, I wanted to apply to. When I broached the topic, he said, "Just to let you know, I got laid off last week". Companies had hiring freezes and were laying off people as well. This led to increased competition for the few companies that were actually hiring. My friend in Shopify, mentioned that they were seeing 10-20 times the normal volume of job applications. I did panic a bit and applied for 1-2 jobs though I didn't necessarily feel drawn to them. &lt;/p&gt;

&lt;h1&gt;
  
  
  Data
&lt;/h1&gt;

&lt;p&gt;Since LinkedIn, where I post too, has a minimal blogging interface, I have my raw data in this &lt;a href="https://docs.google.com/spreadsheets/d/1uPzfNybOdnfBantfdpDK_J_VtvQfM-FcSBNC3jxCSWc/edit?usp=sharing"&gt;Google Sheet&lt;/a&gt; and will use a textual format below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Job Search Period: Apr 9th - June 1st(53 days)&lt;/li&gt;
&lt;li&gt;Over all, I had applied to about 22-25 companies and 11 responded. In the Google Sheet above, you can see the first response in days. Most companies did not send a response after the first automated reply.
&lt;/li&gt;
&lt;li&gt;I got one offer from Bear Health Technologies&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Companies
&lt;/h1&gt;

&lt;p&gt;Here I'll try to list my experiences for select companies.&lt;/p&gt;

&lt;h2&gt;
  
  
  BenchSci
&lt;/h2&gt;

&lt;p&gt;BenchSci is a startup in the pre-clinical R&amp;amp;D space. They were very quick to move with the interview process which I liked. I had 4 technical rounds. I liked talking to all of them. They were smart, friendly and it felt like a high quality team. If you are interviewing with them, they like to give you simpler variants of problems they see in their day to day work. Prepare yourself to get work assignments in an email and quickly import them to your laptop. So, before the interview, prepare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be quickly able to create a Python project, setup virtual environment and run unit tests(pytest).&lt;/li&gt;
&lt;li&gt;Setup an existing postgres database and query editor(e.g. Postico for Mac). You may be given a CSV file so prepare in advance on how to import CSV files into a database.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Shopify
&lt;/h2&gt;

&lt;p&gt;Shopify, according to Glassdoor, had a hiring surge during COVID-19. What I liked best about the interview process was the detailed feedback I got which I really valued. Also, since I had another offer in hand while I was interviewing with Shopify, the coordination team worked hard to accommodate my request to expedite the process. I'm thankful as I know they were getting a lot of applicants. All the interviewers were very friendly as well. &lt;/p&gt;

&lt;h2&gt;
  
  
  Amazon
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;They have a pre-screening programming interview to the normal pre-screening recruiter call :). &lt;/li&gt;
&lt;li&gt;During the online pre-screening programming interview, I mistakenly pressed Escape and then the back button and it logged me out. There is a two minute wait period before you try again :). It's a small thing but I thought you should know.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Zapier
&lt;/h2&gt;

&lt;p&gt;Zapier has been a remote first company even before the pandemic. I found it on a niche job site which promoted companies with better work life balance.  I suspended the process after I got an offer but I really liked my conversation with the recruiter(Stephanie McDonald). She mentioned a phrase which really stuck: "Small Ego, Big Empathy". She used it to describe the kind of people they were looking for.&lt;/p&gt;

&lt;h1&gt;
  
  
  Finally..
&lt;/h1&gt;

&lt;p&gt;I accepted an offer as a Machine Learning Engineer with Bear Health Technologies, a startup making a digital operations software that automatically indexes and summarizes large amounts of medical information reducing the time and cost to prepare and assess a medical brief. Subsequently, I had to suspend my interview process with Keebo, RelationalAI and Zapier. &lt;/p&gt;

&lt;h1&gt;
  
  
  Lessons(and Advice?)
&lt;/h1&gt;

&lt;p&gt;Since the middle of May, I have noticed more activity as companies seem to be ready to open up hiring gradually in the next months. Hopefully these experiences below will still be of use to you.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public Announcement on LinkedIn: I publicly announced on a LinkedIn post that I'm looking for a role. This prompted my ex manager at theScore to reach out to me and ask if I was interested in working again at theScore. Though theScore had a hiring freeze at the time, it was reassuring to know that maybe in a few months time, something could work out with a team I loved and enjoyed working with. This made me more choosy with the roles I was applying to. Another contact connected me to someone who helped me out with other companies and recruiters. A third contact reached out to me to apply to his own startup. Another contact offered to refer me to his company.&lt;/li&gt;
&lt;li&gt;LinkedIn: If there was a company I liked, I would check if there was anyone in my network related to that company. Apart from direct contacts, I got my interview call for Ecobee because I knew someone who knew someone at Ecobee i.e 2nd degree contact. So don't hesitate to reach out to your network to help you to connect with others.&lt;/li&gt;
&lt;li&gt;Building a Network: Out of the 11 companies that responded, 5 were referrals and 2 reached out from my network. Though I'm uncomfortable with the word 'networking', I love connecting :). I realized very early in my career that I must make friends outside my immediate team within the company and outside. Though people think I'm extroverted, I find it uncomfortable to go to new meetups especially when I'm tired in the evening after work. But I kept at it, often, telling myself to meet one new person and then I could go back home. Just one new person, that's it. And this habit has helped me immensely. When I moved to Toronto, I made new connections, found mentors who reignited my drive to go deeper into programming and found all my jobs in Toronto through meetup connections. I even met my co-founder! My job offer at Bear Health came from a contact I have met often at meetups for the past eight years. It takes time to do this but it's never too late. Go for meetups(also virtual) just because they excite you and it's inevitable you'll make friends. We in the tech community are very lucky that there are SO MANY of them. &lt;/li&gt;
&lt;li&gt;Side Projects: As software programmers, we have the wonderful opportunity to try out and work in technologies that we want to get into in the future. I was interested in Julia, did one project on GitHub. RelationalAI was working with Julia and my Julia project stood out when they checked my Github info. Please do consider doing that side project in the technology you want a job in and beef up your resume. &lt;/li&gt;
&lt;li&gt;Update LinkedIn: Amazon reached out because of my LinkedIn Profile.&lt;/li&gt;
&lt;li&gt;Blog: Bear Health Technologies liked my profile because they read my &lt;a href="https://blog.rajivabraham.com/"&gt;blog&lt;/a&gt;. Blogging also ignited my desire to try out LinkedIn for my technical posts. This is an experiment as LinkedIn has minimal support for blogging(IMHO) and programmers generally don't blog on LinkedIn as it heavily seen as a venue for recruiters/job postings etc. But I realized that my entire network is here and 99% of them will never come to my blog :). I see 10-20 views per post but right now I'm still fine with that. If I can pass some of my knowledge to others, though few, I'm happy. Why don't you try it out too and let me know how it goes?&lt;/li&gt;
&lt;li&gt;Cold Calls: No one likes to be cold called. What about warm calls? I sent my resume via LinkedIn to a few people who I had met once or twice. I was totally prepared for them to come back and say that they don't know me enough and don't feel comfortable to send my resume across or some white lie. What I felt bad a bit about was no replies at all. I guess it's hard to say no to people :). And I may one day be in the same position. So if someone can let us know, how to politely decline referral requests, that would be a valuable conversation. &lt;/li&gt;
&lt;li&gt;Unit Tests: Write Unit Tests in interview questions. They seem to help immensely.&lt;/li&gt;
&lt;li&gt;Salary Expectations: Since I was out of the job market for a while due to my startup, I just straight up said that I don't know what to ask and requested the recruiter to tell me what the salary ranges are. External recruiters gave me a good idea about the market while an internal recruiter mentioned their salary range for that role. In this way, I knew where to place myself.&lt;/li&gt;
&lt;li&gt;On Hiring Freezes: I realized that hiring freezes were not absolute. One of my friends approached his manager at a company which had a hiring freeze and the hiring manager said that he would consider making an exception for the right candidate :). I wasn't that candidate but it's good to know that there is some wiggle room.&lt;/li&gt;
&lt;li&gt;Life Project: Consider having a side project which excites you. I have a side project(&lt;a href="https://github.com/RAbraham/mercylog"&gt;Mercylog&lt;/a&gt;) which I call my &lt;code&gt;life project&lt;/code&gt; :). I would work on it after an interview if I thought it didn't go well. When I started waking up later and later as I wasn't working, I decided on working on my side project first thing in the morning or not at all. That made me wake up early :).&lt;/li&gt;
&lt;li&gt;On Connecting: Every interview is an opportunity to meet someone for an hour. Even for jobs that I didn't get, I connected with any interviewer that I liked. In fact, one interviewer, who I thought wasn't impressed with me, invited me to go out for coffee after the pandemic. This just shows me that interviews come and go but I should still take the opportunity to connect with people I like even if their company didn't consider me qualified at that point of time.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Misc: RelationalAI reached out to me when I posted a few questions on a sleepy google group(&lt;code&gt;datalog-cafe&lt;/code&gt;)&lt;/p&gt;
&lt;h1&gt;
  
  
  Resources/Practice
&lt;/h1&gt;

&lt;p&gt;These are the resources I used during my interview prep:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.interviewcake.com/upgrade"&gt;Interview Cake&lt;/a&gt;: I was apprehensive about coding interviews and finishing in time. I decided to embrace the process and get into the minds of experienced programmers. I chose to buy Interview Cake as it was on a steep discount for the pandemic. I liked it as it gave explanations and gave the thought process. I have heard of &lt;a href="http://www.crackingthecodinginterview.com"&gt;Cracking the Coding Interview&lt;/a&gt; as well. If you don't want to pay, I'll recommend trying out &lt;a href="https://www.codewars.com"&gt;Codewars&lt;/a&gt;, LeetCode, HackerRank etc. They are community driven interview question banks with points and skill levels. I have only used Codewars and it was nice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the System Design Interview, I recommend this amazing resource: &lt;a href="https://github.com/donnemartin/system-design-primer"&gt;https://github.com/donnemartin/system-design-primer&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For Data Engineers, this looked nice: &lt;a href="https://github.com/andkret/Cookbook"&gt;https://github.com/andkret/Cookbook&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Salary Negotiation. I found this &lt;a href="https://www.youtube.com/watch?v=sN19aNmjBoU&amp;amp;t"&gt;video&lt;/a&gt; by Josh Doody very informative.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Since most companies used CoderPad, I created my own free account and practiced in the free sandbox. That's how I discovered that CoderPad has &lt;code&gt;pytest&lt;/code&gt; support and I just kept on using it.&lt;/p&gt;
&lt;h1&gt;
  
  
  Gratitude
&lt;/h1&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Coursera: I'm very grateful to Coursera for accepting my application to study the Deep Learning course by Andrew Ng for free.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Coding Cake: I appreciate the drastic reduction in their prices and personalized feedback when I replied to one of their emails.&lt;/p&gt;
&lt;h1&gt;
  
  
  In Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope that my experiences help you in some way. Please know that you are not alone in feeling scared, anxious during these times. We all feel that. The last thing to do is to close yourself to friends and family. If this is your first lay off, I know it's tough and a major downer. But I know, from my experiences and seeing others, we always get jobs sooner or later. Sometimes, we get better jobs :). Best of Luck. &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>DataScript: A modern datastore for the browser</title>
      <dc:creator>Rajiv Abraham</dc:creator>
      <pubDate>Tue, 12 May 2020 20:48:47 +0000</pubDate>
      <link>https://dev.to/rabraham/datascript-a-modern-datastore-for-the-browser-38c0</link>
      <guid>https://dev.to/rabraham/datascript-a-modern-datastore-for-the-browser-38c0</guid>
      <description>&lt;p&gt;This article was originally posted at &lt;code&gt;https://blog.rajivabraham.com/posts/datascript-python&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Purpose.
&lt;/h1&gt;

&lt;p&gt;This blog article will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;give a brief introduction to a new way of managing state on the browser by leveraging a library called &lt;a href="https://github.com/tonsky/datascript"&gt;DataScript&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Though DataScript is a ClojureScript/JavaScript library, we will learn how to call it using &lt;a href="https://blog.rajivabraham.com/posts/brython"&gt;Brython&lt;/a&gt;, a Python implementation that runs on the browser.&lt;/li&gt;
&lt;li&gt;sneak in a tutorial on &lt;a href="https://github.com/RAbraham/mercylog-datascript"&gt;mercylog-datascript&lt;/a&gt; which is a query composer library for DataScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  DataScript(and Datalog)
&lt;/h1&gt;

&lt;p&gt;How do you manage application state in the browser? I'm new to frontend development so I'm sure there are many solutions out there which I don't know about. But let me ask the question from a different perspective. How would a backend developer manage state? She uses a database. She writes SQL queries. Then for the browser, can we use an in-memory datastore and write queries on it?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DataScript&lt;/code&gt; is one such in-memory datastore for the browser. One can create it during page load, insert, delete rows etc. and when the user closes the page, it's gone. It's very light and fast. Also, instead of SQL, it offers a query style called Datalog which is a declarative, logic based query language. I got interested in Datalog when I saw that applications written in its variants reduced the code size by 50% or more(&lt;a href="https://dl.acm.org/doi/10.1145/1755913.1755937"&gt;Overlog&lt;/a&gt;, &lt;a href="https://storage.googleapis.com/pub-tools-public-publication-data/pdf/43462.pdf"&gt;Yedalog&lt;/a&gt;). This is why I got interested in &lt;code&gt;DataScript&lt;/code&gt; in the first place. I have written a brief introduction to the concepts &lt;a href="https://blog.rajivabraham.com/posts/bashlog"&gt;here&lt;/a&gt;. In short, It's like SQL + Recursion.&lt;/p&gt;

&lt;p&gt;But Datalog is not the only reason to use DataScript. That would be like flying in the Boeing 747 for its in-flight entertainment. It has so many other cool features but that's for another post. This post will focus on just the Datalog query interface for DataScript.&lt;/p&gt;

&lt;p&gt;Just to complicate things a bit, &lt;code&gt;DataScript&lt;/code&gt; is actually a ClojureScript library which has a &lt;code&gt;JavaScript&lt;/code&gt; interface too. So in all respects, you would use it cleanly in those languages. &lt;em&gt;But&lt;/em&gt;, I'm interested in Python in the browser and therefore all the examples below will be in a Python implementation in the browser called &lt;a href="https://brython.info/"&gt;Brython&lt;/a&gt;. I have written a &lt;a href="https://blog.rajivabraham.com/posts/brython"&gt;brief introduction&lt;/a&gt; before:&lt;/p&gt;

&lt;p&gt;All the examples below are from the following github &lt;a href="https://github.com/RAbraham/mercylog-datascript-client"&gt;repo&lt;/a&gt;. NOTE: All the files mentioned below take some time to load the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  There is no spoon, Neo.
&lt;/h2&gt;

&lt;p&gt;Cough, before we move on, DataScript is different from your conventional SQL datastores. In conventional SQL databases, when we wish to implement an entity e.g &lt;code&gt;customer&lt;/code&gt;,  we first create a table schema &lt;code&gt;customer&lt;/code&gt; with the &lt;code&gt;attributes&lt;/code&gt;: &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt; for e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE customer (
    name varchar,
    age int
);

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;According to Datomic, the backend database which DataScript is an in-memory implementation of, such an approach is &lt;a href="https://docs.datomic.com/on-prem/schema.html"&gt;rigid&lt;/a&gt;. Hey, I sense it but not well enough to defend it. So, let's not have twitter wars on that one... yet. &lt;/p&gt;

&lt;p&gt;DataScript eschews storing data as separate entities in separate tables(like &lt;code&gt;customer&lt;/code&gt; or &lt;code&gt;person&lt;/code&gt;). Instead, one can see DataScript as a store for &lt;em&gt;attributes&lt;/em&gt; and its values only. So, DataScript prescribes that we only specify the schema for the attributes itself. E.g. &lt;code&gt;name&lt;/code&gt; is &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;age&lt;/code&gt; is &lt;code&gt;integer&lt;/code&gt; but do not group them at all at design time before hand. Instead, the &lt;em&gt;application decides which attributes to group together for a particular instance of that entity&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;In an extreme example to clarify the concepts, the application may decide to store just a customer's name(Rajiv) and his eye color(black) and give the customer an id 1. For another customer, it may store her as id 3 and just store her age(40). Simplistically(and naively incorrect), you can see the database as a single god table with columns &lt;code&gt;entity_id&lt;/code&gt;, &lt;code&gt;attribute&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;  where each row can belong to a different &lt;code&gt;(entity_id, attribute)&lt;/code&gt; composite key. E.g.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;entity_id&lt;/th&gt;
&lt;th&gt;attribute&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;Rajiv&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;age&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;Canada&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;eye_color&lt;/td&gt;
&lt;td&gt;black&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What about the entity &lt;code&gt;2&lt;/code&gt;? He/She is named Canada? Must be a cutie unlike the dull Rajiv. &lt;em&gt;But we don't know, the application knows&lt;/em&gt;. It may not represent a person at all! In this example, the pair (entity id=&lt;code&gt;2&lt;/code&gt;, attribute=&lt;code&gt;name&lt;/code&gt;) could be one attribute and value for an instance of the entity &lt;code&gt;country&lt;/code&gt; e.g. Canada(&lt;em&gt;O Canada, our home and native land... True Patriot Love .. with your public healthcare you command!&lt;/em&gt;). Before you panic and ditch Datomic/DataScript, in practice, the attribute names contain the entity name as well. So it'll be ":customer/name" instead of "name" for Rajiv and ":country/name" instead of "name" for Canada. Or you could still leverage a common &lt;code&gt;name&lt;/code&gt; attribute, your choice. And there is better support for ids than the pitiful example I'm giving here. Also, Imposter Alert, I'm not an expert by any means. I'm learning by doing :). That's my EULA. Please do check out the design principles behind Datomic/DataScript. I think Datomic is a masterpiece in database engineering.&lt;/p&gt;

&lt;p&gt;Let's show you how to add data. For e.g., we can add two dictionaries(Igor and Ivan) to the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db = datascript.empty_db()
db1 = datascript.db_with(db, [{":db/id": 1,
                                "name": "Ivan",
                                "age": 17},
                                {":db/id": 2,
                                "name": "Igor",
                                "age": 35}])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You'll notice that datascript takes a database (&lt;code&gt;db&lt;/code&gt;) and adds data to it and returns a new database &lt;code&gt;db1&lt;/code&gt;. This is because databases in DataScript are immutable. Once created, you can't change it. This makes debugging and reasoning about the code using a database easier. I've written a bit about the general concept of immutability &lt;a href="https://blog.rajivabraham.com/posts/pyrsistent"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For each dictionary, DataScript will add two rows(one for name and another for age) in the single god table. The way DataScript keeps track is with the entity id i.e. &lt;code&gt;:db/id&lt;/code&gt; attribute name which is a reserved attribute name in DataScript.&lt;/p&gt;

&lt;p&gt;So this may be represented in the god table like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;entity_id&lt;/th&gt;
&lt;th&gt;attribute&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;Ivan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;age&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;Igor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;age&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Finally, the query. The query follows the Clojure style of a mixed list. If we want to know the age of the entity whose name is &lt;code&gt;Igor&lt;/code&gt;,&lt;br&gt;
the query would look like &lt;code&gt;[:find ?a :where [?e "name" "Igor"] [?e "age" ?a]]&lt;/code&gt;. The variables with a question mark are called logic variables. If you are familiar with inner joins in SQL, it's very similar. We are saying that if there is some &lt;code&gt;:db/id&lt;/code&gt; (i.e. &lt;code&gt;?e&lt;/code&gt;) whose name is &lt;code&gt;Igor&lt;/code&gt;, for that value of &lt;code&gt;?e&lt;/code&gt;(i.e &lt;code&gt;2&lt;/code&gt;) find a relation for &lt;code&gt;age&lt;/code&gt; (i.e. &lt;code&gt;[?e "age" ?a]&lt;/code&gt;) and return his age(i.e &lt;code&gt;?a&lt;/code&gt;). We should get back &lt;code&gt;35&lt;/code&gt;. The query and the call to the database is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;result = datascript.q('[:find ?a :where [?e "name" "Igor"] [?e "age" ?a]]', db1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The full example is below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html&amp;gt;

&amp;lt;head&amp;gt;
    &amp;lt;meta charset="utf-8"&amp;gt;
    &amp;lt;script type="text/javascript" src="brython.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script type="text/javascript" src="brython_stdlib.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="https://github.com/tonsky/datascript/releases/download/0.18.10/datascript-0.18.10.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body onload="brython(1)"&amp;gt;
&amp;lt;script type="text/python"&amp;gt;
from browser import window, alert
datascript = window.datascript

db = datascript.empty_db()
db1 = datascript.db_with(db, [{":db/id": 1,
                                "name": "Ivan",
                                "age": 17},
                                {":db/id": 2,
                                "name": "Igor",
                                "age": 35}])
result = datascript.q('[:find ?a :where [?e "name" "Igor"] [?e "age" ?a]]', db1)
alert(result)
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Other notes for the above example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We load the &lt;code&gt;Brython&lt;/code&gt; libraries: &lt;code&gt;brython.js&lt;/code&gt; and &lt;code&gt;brython_stdlib.js&lt;/code&gt; to run Python in the browser. &lt;/li&gt;
&lt;li&gt;We load the &lt;code&gt;datascript&lt;/code&gt; library from GitHub using the &lt;code&gt;script&lt;/code&gt; tag . Brython will automatically create a reference for &lt;code&gt;datascript&lt;/code&gt; under the &lt;code&gt;window&lt;/code&gt; object. So we can refer to the module using &lt;code&gt;window.datascript&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;When you open &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/igor-just-datascript.html"&gt;igor-just-datascript.html&lt;/a&gt; in a browser, it should return [[35]]. The return value is always a list.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Mercylog Datascript
&lt;/h2&gt;

&lt;p&gt;Now you could happily continue and query the database with strings like &lt;code&gt;[:find ?a :where [?e "name" "Igor"] [?e "age" ?a]]&lt;/code&gt;. Personally, I find writing code as strings works for simple queries. But it's not easily composable and reusable. So I wrote a Brython library called &lt;a href="https://github.com/RAbraham/mercylog-datascript"&gt;mercylog-datascript&lt;/a&gt; which allows us to use Python to construct the queries. So the same query in &lt;code&gt;mercylog-datascript&lt;/code&gt; becomes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# The original datascript style as str_query
str_query = '[:find ?a :where [?e "name" "Igor"] [?e "age" ?a]]'

# mercylog-datascript style
from mercylog_datascript import DataScriptV1
m = DataScriptV1()
A, E = m.variables('a', 'e')
query = m.query(find=[A], where=[[E, "name", "Igor"], [E, "age", A]])
assert str_query == query.code()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Granted, it's more code than a simple string but I think when the queries become complex and begin to have reusable parts, this style may start paying off.&lt;/p&gt;

&lt;p&gt;All you need to access the &lt;code&gt;mercylog-datascript&lt;/code&gt; library is add the following script tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script src="https://github.com/RAbraham/mercylog-datascript/releases/download/v0.1.4/mercylog_datascript.brython.js"&amp;gt;&amp;lt;/script&amp;gt;`
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The full script is at &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/igor-mercylog-datascript.html"&gt;igor-mercylog-datascript.html&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mercylog-DataScript Queries
&lt;/h3&gt;

&lt;p&gt;Now that you have seen an example, let me show you the current query feature set with a sample dataset of actors, directors and movies. The full dataset is &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/data.json"&gt;here&lt;/a&gt;. Here is an elided subset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
 {":db/id":  100,
  ":person/name": "James Cameron",
  ":person/born": "1954-08-16"},

 {":db/id":  131,
  ":person/name": "Charles Napier",
  ":person/born": "1936-04-12",
  ":person/death": "2011-10-05"},
  ....

  {":db/id":  200,
  ":movie/title": "The Terminator",
  ":movie/year":  1984,
  ":movie/director":  100,
  ":movie/cast":  [101,
               102,
               103],
  ":movie/sequel":  [207]},

 {":db/id":  201,
  ":movie/title": "First Blood",
  ":movie/year":  1982,
  ":movie/director":  104,
  ":movie/cast":  [105,
               106,
               107],
  ":movie/sequel":  [209]},
....

]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here is the code to access the raw dataset and a simple pattern access as above with the Igor example. The code is &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/simple_data_pattern.html"&gt;here&lt;/a&gt;. Below we want to know the birthdate of &lt;code&gt;Linda Hamilton&lt;/code&gt; and it will return &lt;code&gt;[['1956-09-26']]&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html&amp;gt;

&amp;lt;head&amp;gt;
    &amp;lt;meta charset="utf-8"&amp;gt;
    &amp;lt;script type="text/javascript" src="brython.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script type="text/javascript" src="brython_stdlib.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="https://github.com/RAbraham/mercylog-datascript/releases/download/v0.1.4/mercylog_datascript.brython.js"&amp;gt;&amp;lt;/script&amp;gt;

    &amp;lt;script src="https://github.com/tonsky/datascript/releases/download/0.18.10/datascript-0.18.10.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body onload="brython(1)"&amp;gt;
&amp;lt;script type="text/python"&amp;gt;
from browser import window, alert, console
datascript = window.datascript

from mercylog_datascript import DataScriptV1
m = DataScriptV1()
import urllib.request, json
data_file_url = 'https://raw.githubusercontent.com/RAbraham/mercylog-datascript-client/master/data.json'
console.log('Loading File')
with urllib.request.urlopen(data_file_url) as url:
    result = json.loads(url.read())
console.log('End loading file')

db = datascript.empty_db()
db2 = datascript.db_with(db, result)

e, name, born = m.variables('e', 'name', 'born')

query = m.query(find=[born], where=[[e, ":person/name", "Linda Hamilton"], [e, ":person/born", born]])
q = query.code()
result = datascript.q(q, db2)
alert(result)  # [['1956-09-26']]


&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Henceforth, I'll only focus on the &lt;code&gt;mercylog-datascript&lt;/code&gt; query builder and how it supports DataScript.&lt;/p&gt;

&lt;p&gt;Let's start with something simple. How do we just get the id(i.e &lt;code&gt;:db/id&lt;/code&gt;) of a person? As shown in &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/entity.html"&gt;entity.html&lt;/a&gt;, the following query returns &lt;code&gt;[[102]]&lt;/code&gt; for  &lt;code&gt;Linda Hamilton&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;e = m.variables('e')
query = m.query(find=[e], where=[[e, ":person/name", "Linda Hamilton"]])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's great, but sometimes you want to create a parameterized query i.e. a query that can be used with different values. Let's generalize the query above and then we can use it for different values. We do this by adding a &lt;code&gt;parameters&lt;/code&gt; key to our &lt;code&gt;query&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/parameterized_queries.html"&gt;parameterized_queries.html&lt;/a&gt;, you'll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# [:find ?e :in $ ?name :where [?e ":person/name" ?name]]
e, name = m.variables('e', 'name')
query = m.query(find=[e], parameters=[name], where=[[e, ":person/name", name]])
q = query.code()
result1 = datascript.q(q, db2, 'Linda Hamilton')
result2 = datascript.q(q, db2, 'Sylvester Stallone')
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see above, the same query can be used to query &lt;code&gt;Linda Hamilton&lt;/code&gt;  and &lt;code&gt;Sylvester Stallone&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Sometimes, you don't care about the entity, when doing a search. For e.g, you just want all the movie titles. In that case, &lt;code&gt;mercylog-datascript&lt;/code&gt; provides the &lt;code&gt;m._&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/underscore.html"&gt;underscore.html&lt;/a&gt;, you'll find:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# [:find ?title :where [_ ":movie/title" ?title]]
title = m.variables('title')
query = m.query(find=[title], where=[[m._, ":movie/title", title]])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This would return&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[['First Blood'], ['Terminator 2: Judgment Day'], ....  ['Terminator 3: Rise of the Machines']]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/attr.html"&gt;attr.html&lt;/a&gt;, we show how to find out the attributes which are commonly associated with a particular attribute(i.e. ":person/name"). To reiterate, as DataScript does not have a fixed schema, it's possible for a customer record c1 to only have a name but another record c2 to have a name and age.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# DataScript Query: [:find ?attribute :where [?person ":person/name"] [?person ?attribute]]
person, attribute = m.variables('person', 'attribute')
query = m.query(find=[attribute],
                where=[[person, ":person/name"],
                       [person, attribute]])

q = query.code()
result = datascript.q(q, db2) # [[':person/born'], [':person/name'], [':person/death']]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Above, we find out that an entity which has an attribute &lt;code&gt;:person/name&lt;/code&gt; can also have one or more of &lt;code&gt;[[':person/born'], [':person/name'], [':person/death']]&lt;/code&gt;. The slow reader who didn't try to read this in the elevator may have noticed that previously our list in the &lt;code&gt;where&lt;/code&gt; clause were of size three but when we do such kind of meta searches, we can just pass lists of size 2(e.g. &lt;code&gt;[person, attribute]&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Now, you sigh and say, this is all good but no language is a language unless it allows you to create functions. In &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/transformation.html"&gt;transformation.html&lt;/a&gt;, we see an example of passing a user defined function(&lt;code&gt;get_age&lt;/code&gt;) to be executed against the database.&lt;br&gt;
In the code snippet below, notice &lt;code&gt;[get_age(born), age]&lt;/code&gt;. You could see this as &lt;code&gt;age = get_age(born)&lt;/code&gt; for different values of &lt;code&gt;born&lt;/code&gt; and you could reuse that in your query. In our case, we just ask for it directly in &lt;code&gt;find&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
 Since it's user defined, we add &lt;code&gt;get_age&lt;/code&gt; to the &lt;code&gt;parameters&lt;/code&gt; argument for &lt;code&gt;query&lt;/code&gt; as well and pass &lt;code&gt;get_age.function&lt;/code&gt; to the DataScript query engine as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# DataScript Query:[:find ?age :in $ ?get_age ?name :where [?p ":person/name" ?name] [?p ":person/born" ?born] [(?get_age ?born) ?age]]
from datetime import datetime
current_year = int(datetime.today().strftime('%Y'))
get_age = m.function('get_age', lambda born: (current_year - int(born.split('-')[0])) )

born, p, age, name = m.variables('born', 'p', 'age', 'name')
query = m.query(find=[name, age],
                parameters=[get_age, name],
                where=[[p, ":person/name", name],
                       [p, ":person/born", born],
                       [get_age(born), age]])

q = query.code()
result = datascript.q(q, db2, get_age.function, "Richard Crenna")
alert(result) #[['Richard Crenna', 94]]


&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ok, you say this is simple stuff, yawn, what about SQL like aggregate functions? DataScript has you covered. In &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/aggregates.html"&gt;aggregates.html&lt;/a&gt;, we show the use of inbuilt functions of DataScript i.e. &lt;code&gt;agg.max(age)&lt;/code&gt;. As a bonus, we now show how to combine that with a user defined function(&lt;code&gt;get_age&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# DataScript Query:[:find (max ?age) :in $ ?get_age :where [?p ":person/name" ?name] [?p ":person/born" ?born] [(?get_age ?born) ?age]]
from datetime import datetime
current_year = int(datetime.today().strftime('%Y'))
get_age = m.function('get_age', lambda born: (current_year - int(born.split('-')[0])) )
agg = m.agg
born, p, age, name = m.variables('born', 'p', 'age', 'name')
query = m.query(find=[agg.max(age)],
                parameters=[get_age],
                where=[[p, ":person/name", name],
                       [p, ":person/born", born],
                       [get_age(born), age]])

q = query.code()
result = datascript.q(q, db2, get_age.function)
alert(result) # [[94]]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What about SQL where like clauses? We have filters in DataScript too. It's basically a user defined function in it's own row. For e.g, in &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/predicate2.html"&gt;predicate2.html&lt;/a&gt;(because getting &lt;code&gt;predicate1.html&lt;/code&gt; to work made me cry), I'm going to make a simple filter function called &lt;code&gt;born_before_1950&lt;/code&gt; to filter out the wiser actors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# DataScript Query: [:find ?person :in $ ?born_before_1950 :where [?person ":person/born" ?birth_date] [(?born_before_1950 ?birth_date)]]
person, birth_date = m.variables('person', 'birth_date')
born_func = lambda x: int(x.split('-')[0]) &amp;lt; 1950
born_before_1950 = m.function('born_before_1950', born_func)
query = m.query(find=[person],
                parameters=[born_before_1950],
                where=[[person, ":person/born", birth_date],
                       [born_before_1950(birth_date)]])
q = query.code()
result = datascript.q(q, db2, born_before_1950.function)
alert(result) # [[148], [119], [146], [105], [136], [116], [135], [145], [111], [114], [118], [115], [147], [104], [139], [110], [133], [131], [140], [101], [123], [142], [137], [138], [106], [107], [113], [124], [130]]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can leverage ClojureScript inbuilt functions too. As seen in &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/inbuilt_function3.html"&gt;inbuilt_function3.html&lt;/a&gt;(why &lt;code&gt;3&lt;/code&gt;?, you guessed it ;)), we can call inbuilt functions like &lt;code&gt;&amp;lt;&lt;/code&gt;. You still leverage the &lt;code&gt;m.function&lt;/code&gt; method but since you don't pass your own user defined function, &lt;code&gt;mercylog-datascript&lt;/code&gt; will assume that you are trying to call an inbuilt function. You can call that convenient or over smart, only time will tell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# DataScript Query: [:find ?title :where [?movie ":movie/title" ?title] [?movie ":movie/year" ?year] [(&amp;lt; ?year 1984)]]
title, movie, year = m.variables('title', 'movie', 'year')
lt = m.function("&amp;lt;")
query = m.query(find=[title],
                where=[[movie, ":movie/title", title],
                       [movie, ":movie/year", year],
                       [lt(year, 1984)]])

q = query.code()
alert(q)
result = datascript.q(q, db2)
alert(result) # [['First Blood'], ['Alien'], ['Mad Max'], ['Mad Max 2']

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But most of the fun happens when we link different sources of data together to make money. For e.g. you may call a service which gives you the box office numbers for popular movies and you want to link that with the data in your database and find out the corresponding directors. &lt;/p&gt;

&lt;p&gt;This is similar to an inner join in SQL between two tables but in this case, one side is a 'table' in DataScript and the other side is your in-memory structure which you obtain after calling the API for the service. Suppose you store the result of the API call in an in-memory list(&lt;code&gt;title_box_office_pairs&lt;/code&gt; below). You need to tell DataScript about it's structure. So you specify it in the &lt;code&gt;parameters&lt;/code&gt; argument as &lt;code&gt;m.collection([title, box_office])&lt;/code&gt; and then later pass &lt;code&gt;title_box_office_pairs&lt;/code&gt; to &lt;code&gt;datascript.q()&lt;/code&gt; later.  Then you could use the logic variable &lt;code&gt;title&lt;/code&gt; and use that to link to the data in the DataScript store. Code snippet below and full code &lt;a href="https://github.com/RAbraham/mercylog-datascript-client/blob/master/parameterized_queries_relations.html"&gt;here&lt;/a&gt;,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# DataScript query: [:find ?director ?box_office :in $ [[?title ?box_office]] :where [?p ":person/name" ?director] [?movie ":movie/director" ?p] [?movie ":movie/title" ?title]]

movie, p, title, box_office, director = m.variables('movie', 'p', 'title', 'box_office', 'director')
# title_box_office_pairs below could have been obtained from some api call.
title_box_office_pairs = [
 ["Die Hard", 140700000],
 ["Alien", 104931801],
 ["Lethal Weapon", 120207127],
 ["Commando", 57491000],
]
query = m.query(find=[director,
                      box_office],
                parameters=[m.collection([title, box_office])],
                where=[[p, ":person/name", director],
                       [movie, ":movie/director", p],
                       [movie, ":movie/title", title]])

q = query.code()
result = datascript.q(q, db2, title_box_office_pairs)
alert(result) # [['Richard Donner', 120207127], ['Mark L. Lester', 57491000], ['John McTiernan', 140700000], ['Ridley Scott', 104931801]]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, we can define rules. Let's say we want to make a rule: Two people are mates if their names match(hey, that's a good reason to be mates, no?). In Datalog, one would write it like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mate(E1, E2) &amp;lt;= Name(N, E1), Name(N, E2)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;i.e. any person &lt;code&gt;E1&lt;/code&gt; is a mate of any person &lt;code&gt;E2&lt;/code&gt; if they both have the name &lt;code&gt;N&lt;/code&gt;. Again &lt;code&gt;N&lt;/code&gt; here is a logic variable which could represent all the names in the database.&lt;br&gt;
In mercylog-datascript, you would write the above as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;e1, e2, n = m.variables('e1', 'e2', 'n')

mate = m.relation('mate')
r = m.rule(mate(e1, e2), [[e1, "name", n],
                          [e2, "name", n]])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A complete code listing is below. We also show to add a &lt;code&gt;m.function&lt;/code&gt; to choose those rows where &lt;code&gt;e1&lt;/code&gt; has a bigger id than &lt;code&gt;e2&lt;/code&gt;. I know! It does not make sense but I've been labouring on this post for three weeks and it's time to wrap up :P:&lt;/p&gt;

&lt;p&gt;NOTE: There is some boilerplate code for now to send the rule as a parameter to the query:&lt;code&gt;rule_code = '[' + r.code() + ']'&lt;/code&gt;. I'll look into improving it if a thousand of you star this project on Github(Yeah, ain't going to happen, I know :))&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from mercylog_datascript import DataScriptV1
m = DataScriptV1()
db = datascript.empty_db()

db2 = datascript.db_with(datascript.empty_db({"age": {":db/index": True}}),
                 [{ ":db/id": 1, "name": "Ivan", "age": 15 },
                  { ":db/id": 2, "name": "Petr", "age": 37 },
                  { ":db/id": 3, "name": "Ivan", "age": 37 }]);

e1, e2, p, title, n = m.variables('e1', 'e2', 'p', 'title', 'n')
mate = m.relation('mate')
gt = m.function('&amp;lt;')
query = m.query(find=[e1, e2],
                where=[mate(e1, e2),
                       [gt(e1, e2)]])
q = query.code()
alert(q)

r = m.rule(mate(e1, e2), [[e1, "name", n],
                          [e2, "name", n]])
rule_code = '[' + r.code() + ']'
alert(rule_code)
result = datascript.q(q, db2, rule_code)

alert(result) # [[1,3]]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's about it. If you came so far, I love you. I really do. Call me.&lt;/p&gt;

&lt;h3&gt;
  
  
  If you loved the above.
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;DataScript has two more APIs in addition to the Datalog API:

&lt;ul&gt;
&lt;li&gt;Entity API: I think this is similar in concept to graph database like query languages. I leave it to the reader to investigate&lt;/li&gt;
&lt;li&gt;Pull API: Similar to GraphQL&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;If you want to learn about more about the DataScript syntax, check out this &lt;a href="http://www.learndatalogtoday.org/"&gt;site&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The Datomic Data Model which DataScript is inspired about is mentioned &lt;a href="https://docs.datomic.com/cloud/whatis/data-model.html"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>Brython: On replacing JavaScript with Python for front-end development</title>
      <dc:creator>Rajiv Abraham</dc:creator>
      <pubDate>Tue, 05 May 2020 17:13:35 +0000</pubDate>
      <link>https://dev.to/rabraham/brython-on-replacing-javascript-with-python-for-front-end-development-45d7</link>
      <guid>https://dev.to/rabraham/brython-on-replacing-javascript-with-python-for-front-end-development-45d7</guid>
      <description>&lt;p&gt;This article was originally posted at &lt;code&gt;https://blog.rajivabraham.com/posts/brython&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Purpose.
&lt;/h1&gt;

&lt;p&gt;This blog article will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;give a brief introduction to using &lt;a href="https://brython.info/"&gt;Brython&lt;/a&gt;, a Python implementation for front-end development on the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The entire project is &lt;a href="https://github.com/RAbraham/brython-blog"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Jealous of JavaScript programmers, a cabal of Python programmers secretly met to discuss the future of Python in this apocalyptic world. JavaScript was everywhere and eating Python's lunch. With Node.js, JavaScript had invaded Python territory and ended its dominance as everyone's favorite language after Ruby(not very dominant then, is it? Mr. Author). It was time to make a thrust into the heart of JavaScript land: The Browser.&lt;/p&gt;

&lt;h1&gt;
  
  
  Don't forget your history(and future)
&lt;/h1&gt;

&lt;p&gt;The cabal were not the only gentlemen concerned with this dilemma. The author of &lt;a href="https://www.transcrypt.org/"&gt;Transcrypt&lt;/a&gt; believed in poison and espionage. He decided to write a Python compiler which compiled to JavaScript code. Like good poison, there was no trace of Python. It looked very promising. But the author of this boring post found a bug and raised an issue which was unsolved/unattended for ages. So he felt it wise to abandon this side plot.&lt;/p&gt;

&lt;p&gt;Others wanted to learn from history. Just immigrate the entire family. At least, that's what &lt;a href="https://hacks.mozilla.org/2019/04/pyodide-bringing-the-scientific-python-stack-to-the-browser/"&gt;Pyodide&lt;/a&gt; thought of doing. Their strategy was to create an enclave on the side with a full Python Interpreter which can run Python code. Thus you could run any Python code including most of the data science stack which contains C language bindings (e.g. Numpy, Pandas). &lt;/p&gt;

&lt;p&gt;This looks very promising too. But on initial lazy tests by this author, the initial page load was a bit slow(The real reason was that the author also could not find an easy way to make this work and was happy to not pursue it any further.)&lt;/p&gt;

&lt;p&gt;So the cabal decided to do what every cabal is supposed to do i.e. create another Python to JavaScript compiler but this time, compile it to JavaScript when the page loads(unlike Transcrypt which compiles to JavaScript ahead of time). Thus, the fellowship of Brython was formed. One snake to rule them all. &lt;/p&gt;

&lt;h1&gt;
  
  
  Hello World
&lt;/h1&gt;

&lt;p&gt;Let's code up the customary 'Hello World'&lt;/p&gt;

&lt;p&gt;The Brython paratroopers(compiler) is here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script type="text/javascript"
       src="https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js"&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We activate it on page load&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body onload="brython()"&amp;gt;
...
&amp;lt;/body&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Within the &lt;code&gt;body&lt;/code&gt; tag above, we write the Brython Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script type="text/python"&amp;gt;
from browser import document

document &amp;lt;= "Hello World"
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We just add &lt;code&gt;Hello World&lt;/code&gt; to the document element. Hmmm. That was easy.&lt;/p&gt;

&lt;p&gt;In complete form, it's shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="utf-8"&amp;gt;
    &amp;lt;script type="text/javascript"
        src="https://cdn.jsdelivr.net/npm/brython@3.8.8/brython.min.js"&amp;gt;
    &amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body onload="brython()"&amp;gt;

&amp;lt;script type="text/python"&amp;gt;
from browser import document

document &amp;lt;= "Hello World"
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will simply print "Hello World" to the page. &lt;/p&gt;

&lt;h1&gt;
  
  
  Calculator
&lt;/h1&gt;

&lt;p&gt;Let's now make a calculator(code courtesy: Brython). The full code is &lt;a href="https://github.com/RAbraham/brython-blog/blob/master/calculator.html"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8jaMla2b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/RAbraham/brython-blog/master/brython-calculator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8jaMla2b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/RAbraham/brython-blog/master/brython-calculator.png" alt="alt text" title="Calculator in Brython"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, you were right. We do need a table. Let's make one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from browser import document, html
calc = html.TABLE()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's add the first row only. Just the display box(we'll name it &lt;code&gt;result&lt;/code&gt;) and &lt;code&gt;C&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;calc &amp;lt;= html.TR(html.TH(html.DIV("0", id="result"), colspan=3) +
                html.TD("C"))

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Yes, I'm not very sure of this &lt;code&gt;&amp;lt;=&lt;/code&gt; syntax either. But hey, for such a lovely library, I'll settle for it too :).&lt;/p&gt;

&lt;p&gt;Let's now add the number pad&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lines = ["789/", "456*", "123-", "0.=+"]
calc &amp;lt;= (html.TR(html.TD(x) for x in line) for line in lines)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, we add &lt;code&gt;calc&lt;/code&gt; to the &lt;code&gt;document&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document &amp;lt;= calc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that's all good. How do we make it work? First, we need to capture a reference to the &lt;code&gt;result&lt;/code&gt; element to manipulate it when the number pad is pressed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;result = document["result"] # direct access to an element by its id
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we need to update the &lt;code&gt;result&lt;/code&gt; whenever any element in the number pad is clicked. Let's make an event handler. We'll trust the Brython developers that this code works. Notice the manipulation of &lt;code&gt;result&lt;/code&gt; based on the button you clicked.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def action(event):
    """Handles the "click" event on a button of the calculator."""
    # The element the user clicked on is the attribute "target" of the
    # event object
    element = event.target
    # The text printed on the button is the element's "text" attribute
    value = element.text
    if value not in "=C":
        # update the result zone
        if result.text in ["0", "error"]:
            result.text = value
        else:
            result.text = result.text + value
    elif value == "C":
        # reset
        result.text = "0"
    elif value == "=":
        # execute the formula in result zone
        try:
            result.text = eval(result.text)
        except:
            result.text = "error"

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, we associate the event handler above to the &lt;code&gt;click&lt;/code&gt; event of all buttons.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for button in document.select("td"):
    button.bind("click", action)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;See, how easy it is when someone else writes the code :P. But seriously, Brython is a wonderful work of engineering and perhaps the best display of programmer love for their beloved Python language. Please support the developers, at least with a star on their Github &lt;a href="https://github.com/brython-dev/brython"&gt;repo&lt;/a&gt;!&lt;/p&gt;

&lt;h1&gt;
  
  
  For the advanced reader
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;One can also integrate third party libraries like Vue.js as shown &lt;a href="https://brython.info/gallery/test_vue.html"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A great in depth explanation of the concepts can be found &lt;a href="https://anvil.works/blog/python-in-the-browser-talk"&gt;here&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>Introduction to PureScript: Twitter Search API</title>
      <dc:creator>Rajiv Abraham</dc:creator>
      <pubDate>Wed, 01 Apr 2020 17:55:43 +0000</pubDate>
      <link>https://dev.to/rabraham/introduction-to-purescript-twitter-search-api-3bk4</link>
      <guid>https://dev.to/rabraham/introduction-to-purescript-twitter-search-api-3bk4</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is an ported, edited version of the &lt;a href="https://medium.com/@rajiv.abraham/introduction-purescript-twitter-fec6df5276dc"&gt;original&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TLDR&lt;/em&gt;: I wrote this in a fiction format for fun. The actual code is in the &lt;a href="https://github.com/RAbraham/blog-twitter-purescript-simple"&gt;repo&lt;/a&gt;. Also, I'm new to FP so this is newbie code. I can refactor it to be elegant but I want to keep this simple for beginners.&lt;/p&gt;

&lt;h2&gt;
  
  
  Twitter Storm
&lt;/h2&gt;

&lt;p&gt;Kim Kardashian felt uneasy as soon as she woke up. She had just used the r-word yesterday and suffered a huge &lt;a href="https://www.cosmopolitan.com/entertainment/a24515906/kim-kardashian-r-word-halloween-costume/"&gt;backlash&lt;/a&gt;. She felt vulnerable about her twitter following and needed to be reassured. She had to do something different. Yes, she could just type her name in the Twitter App and see what people were saying about her. But she had secretaries for that. No, she had to do what no other celeb had done before. She would code!&lt;/p&gt;

&lt;p&gt;What language though? A language which is nice and clean and pure. So she googles around and discovers PureScript! She installs it in a breeze while wondering about this Mr. Java Script guy who was always complaining online on how difficult it was. Sigh. Ok, what next?&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading Twitter credentials
&lt;/h2&gt;

&lt;p&gt;First, she has to read her Twitter credentials from a file. Yes, she could hard code the passwords in the program but she's a celeb. She knows &lt;em&gt;Security&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So, she got her credentials from Twitter and created a file like below at &lt;code&gt;config/twitter_credentials.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "consumer_key": "KimMama",
  "consumer_secret": "KimLikesToCode",
  "access_token": "KimDoesNotKnowWhatThisIsFor",
  "access_token_secret": "KimThinksTwitterHasGoneMad"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;She built a JavaScript like object in PureScript(called records) using &lt;code&gt;type&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type TwitterCredentials =
  { consumer_key :: String
  , consumer_secret :: String
  , access_token :: String
  , access_token_secret :: String
  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How do we read this file?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Node.Encoding&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Node.FS.Aff&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;readTextFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;readConfigStr&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Aff&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;readConfigStr&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;readTextFile&lt;/span&gt; &lt;span class="kt"&gt;UTF8&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;import Node.Encoding (Encoding(..))&lt;/code&gt; meant import the type constructor &lt;code&gt;Encoding&lt;/code&gt; and  the &lt;code&gt;..&lt;/code&gt; meant import all it's data constructors as well, one of which is &lt;code&gt;UTF8&lt;/code&gt;. Since she is a celeb and she is never wrong, type constructors are like abstract base types and data constructors are like normal OOP constructors but fancier. You can have data constructors with different names and you can even treat them like Enumerations in switch/case like statements(Kim's BFF liked to call them pattern matching).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Aff&lt;/code&gt; stands Asynchronous Effect(the synchronous effect is called &lt;code&gt;Effect&lt;/code&gt;). These effects &lt;em&gt;represent&lt;/em&gt; an action that the program would like to take, but &lt;em&gt;not executed&lt;/em&gt; yet. Whaaa?&lt;/p&gt;

&lt;p&gt;If Kim wanted to call Khloe for lunch, buy flowers for her mother and type her next tweet... She wouldn't be the person doing it, would she? It would be her &lt;em&gt;secretary&lt;/em&gt;! All, she would do is &lt;code&gt;text&lt;/code&gt; her secretary commands to do this thing but it wouldn't happen until her secretary &lt;em&gt;actually executed&lt;/em&gt; the commands at a later time!&lt;/p&gt;

&lt;p&gt;In the same way, &lt;code&gt;Aff&lt;/code&gt;(and &lt;code&gt;Effect&lt;/code&gt;) were like &lt;code&gt;texts&lt;/code&gt; by Kim to her new secretary &lt;code&gt;PureScript&lt;/code&gt;. It was a way of telling &lt;code&gt;PureScript&lt;/code&gt; that she wanted them to be done but it was just a &lt;em&gt;representation&lt;/em&gt; of a command, not the actual &lt;em&gt;execution&lt;/em&gt;  of the command. By representation, it just meant it was a value, just like the way number &lt;code&gt;3&lt;/code&gt; or &lt;code&gt;"a_string"&lt;/code&gt; or a JavaScript object were values.&lt;/p&gt;

&lt;p&gt;For e.g., imagine the following pseudocode in an imperative language(e.g. Python):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1: x = print("A String")
2: x
3: x

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output would be&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;A string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;execution&lt;/code&gt; and &lt;code&gt;evaluation&lt;/code&gt; of the &lt;code&gt;print&lt;/code&gt; statement both happen at line 1.&lt;/p&gt;

&lt;p&gt;But in a functional language, the above pseudocode would be something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1: run(
2: let x = print("A String")
3: x
4: x
5: )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the output would be&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;A String
A String
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;let&lt;/code&gt; is like the variable assignment in imperative code.&lt;/p&gt;

&lt;p&gt;Only the evaluation happens at lines 2-4 but &lt;em&gt;not the execution&lt;/em&gt;. The execution happens inside &lt;code&gt;run&lt;/code&gt;. So before the program is given to run, &lt;code&gt;x&lt;/code&gt; replaced at lines 3 and 4 to be &lt;code&gt;print("A String")&lt;/code&gt;. Note, the &lt;code&gt;print&lt;/code&gt; has different interpretations. In the imperative setting, it executes a command, but in the functional setting, it executes nothing, just returns back a value representing an action for future execution by the &lt;code&gt;run&lt;/code&gt; procedure.&lt;/p&gt;

&lt;p&gt;Another viewpoint is that most applications always start with the &lt;code&gt;main&lt;/code&gt; function. In PureScript, perhaps the simplest program one could write is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Effect.Console (log)
main:: Effect Unit
main = log "Product Placement Here. ;)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The signature for &lt;code&gt;log&lt;/code&gt; is &lt;code&gt;log :: String -&amp;gt; Effect Unit&lt;/code&gt;. &lt;code&gt;Unit&lt;/code&gt; stands for nothing, as in, we don't expect anything back from the console.&lt;/p&gt;

&lt;p&gt;And like the pseudocode above, what happens within PureScript code, unseen by the programmer is something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;run(main)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kim felt a chill through her spine. She regretted not taking programming seriously in school.&lt;/p&gt;

&lt;p&gt;Ok, &lt;code&gt;readConfigStr&lt;/code&gt; returned a &lt;code&gt;Aff String&lt;/code&gt; but she needed to convert it to our &lt;code&gt;TwitterCredentials&lt;/code&gt; record. She asked her secretary for technology to find a library for her and she found &lt;a href="https://purescript-simple-json.readthedocs.io/en/latest/"&gt;PureScript-Simple-JSON&lt;/a&gt; by a guy called &lt;a href="https://github.com/justinwoo"&gt;Justin Woo&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Simple.JSON as SimpleJSON
import Data.Either (Either(..))

parseConfig :: String -&amp;gt; Either String TwitterCredentials
parseConfig s =
  case SimpleJSON.readJSON s of
    Left error -&amp;gt; Left (show error)
    Right (creds :: TwitterCredentials) -&amp;gt; Right creds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;parseConfig&lt;/code&gt; has an &lt;code&gt;Either String TwitterCredentials&lt;/code&gt; in it's signature. It's like an union type. The result could either be a String(an error string) or the actual credentials. PureScript defines &lt;code&gt;Either&lt;/code&gt; as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data Either a b = Left a | Right b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if we want to return a string, we return &lt;code&gt;Left "my error string"&lt;/code&gt;, the actual credentials as &lt;code&gt;Right creds&lt;/code&gt;. That way, the person calling &lt;code&gt;parseConfig&lt;/code&gt; knows which is which.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;parseConfig&lt;/code&gt;, &lt;code&gt;SimpleJSON.readJSON&lt;/code&gt; returned an &lt;code&gt;Either&lt;/code&gt; but Kim didn't want to deal with the complex &lt;code&gt;Left&lt;/code&gt; type, so she just converted that to a string using &lt;code&gt;show&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now it was just a matter of calling &lt;code&gt;readConfigStr&lt;/code&gt; and passing the value to &lt;code&gt;parseConfig&lt;/code&gt;. Something like this pseudocode&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cStr = readConfigStr path
return parseConfig cStr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But she couldn't make it compile! She started panicking and thought of what would happen if the word got out and Taylor Swift found out. &lt;em&gt;The Shame&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;"Try the &lt;em&gt;do&lt;/em&gt; notation", said a voice from behind.&lt;/p&gt;

&lt;p&gt;Kim swivelled back and her mouth opened with surprise.&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;Kanye&lt;/em&gt;! I didn't know you knew PureScript!"&lt;/p&gt;

&lt;p&gt;"Nah, PureScript is for hipsters. I'm old school. I like my Haskell."&lt;/p&gt;

&lt;p&gt;He continued, "The &lt;em&gt;do&lt;/em&gt; notation allows you to extract the &lt;code&gt;String&lt;/code&gt; from &lt;code&gt;Aff String&lt;/code&gt; and gives you the illusion of the pseudocode above."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;readConfig :: String -&amp;gt; Aff (Either String TwitterCredentials)
readConfig path = do
  cStr &amp;lt;- readConfigStr path
  pure $ parseConfig cStr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"What's &lt;code&gt;pure $&lt;/code&gt; for?", asked Kim?&lt;/p&gt;

&lt;p&gt;Kanye sighed. He knew the author of this post was in a hurry to move on to doing &lt;a href="https://blog.rajivabraham.com/posts/purescript-serverless"&gt;cooler stuff&lt;/a&gt; and didn't want to get into monads in this post. So he bailed too.&lt;/p&gt;

&lt;p&gt;First &lt;code&gt;$&lt;/code&gt;. That's just a simple way of saying consider everything after as one value. For e.g.&lt;br&gt;
&lt;code&gt;show $ SimpleJSON.readJSON s&lt;/code&gt; meant &lt;code&gt;show (SimpleJSON.readJSON s)&lt;/code&gt; instead of &lt;code&gt;(show SimpleJSON.readJSON) s&lt;/code&gt;. Kim approved. She liked &lt;code&gt;$&lt;/code&gt; signs.&lt;/p&gt;

&lt;p&gt;Kanye then braced himself for his 'simplification' of &lt;code&gt;pure&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;"You noticed that it was &lt;code&gt;cStr &amp;lt;- readConfigStr path&lt;/code&gt; and not &lt;code&gt;let cStr = readConfigStr path&lt;/code&gt;. The &lt;code&gt;&amp;lt;-&lt;/code&gt; is syntax sugar which make it look like an &lt;code&gt;=&lt;/code&gt;. But what is really happening underneath is something very similar to callbacks. The &lt;code&gt;Aff String&lt;/code&gt; type has to be given a function to work on the &lt;code&gt;String&lt;/code&gt; value within it. But this function can't just be &lt;code&gt;cStr -&amp;gt; parseConfig cStr&lt;/code&gt;. The function has to return back an &lt;code&gt;Aff something&lt;/code&gt;. &lt;code&gt;pure&lt;/code&gt; is a constructor. In this context of &lt;code&gt;Aff&lt;/code&gt;, when we say &lt;code&gt;pure something&lt;/code&gt;, it's like saying &lt;code&gt;new Aff(something)&lt;/code&gt; or in our case, it's like saying &lt;code&gt;new Aff(parseConfig(cStr))&lt;/code&gt;"&lt;/p&gt;

&lt;p&gt;Kim beamed at Kanye. He looked so hot right now. She wanted him so bad.&lt;/p&gt;
&lt;h2&gt;
  
  
  Bearer Token from Twitter.
&lt;/h2&gt;

&lt;p&gt;Great, that gave her the credentials but she needed a bearer token from Twitter which she would then use to get the results. How does one call the Twitter endpoint in PureScript? She beckoned her secretary for technology to find her a library. Her secretary came back running.&lt;/p&gt;

&lt;p&gt;"I found a library called &lt;a href="https://github.com/justinwoo/purescript-milkis"&gt;Milkis&lt;/a&gt;... &lt;em&gt;again by Justin Woo&lt;/em&gt;!"&lt;/p&gt;

&lt;p&gt;Kim's eyes sharpened with intent. She wondered out aloud, "Do you think this Justin guy is a celebrity in the PureScript world? Hmmmm &lt;em&gt;make my agent call his agent. Let's do a reality show together.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;Kim first created a method to construct the authorization string from the credentials and encode it in &lt;code&gt;Base64&lt;/code&gt;. The &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt; was like an append operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Data.String.Base64 as S
authorizationStr :: TwitterCredentials -&amp;gt; String
authorizationStr credentials =
  S.encode $ credentials.consumer_key &amp;lt;&amp;gt; ":" &amp;lt;&amp;gt; credentials.consumer_secret

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;She then made a simple &lt;code&gt;fetch&lt;/code&gt; helper method from &lt;code&gt;Milkis&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Milkis as M
import Milkis.Impl.Node (nodeFetch)


fetch :: M.Fetch
fetch = M.fetch nodeFetch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;She then created a method to get the bearer token string or return a string as error(in the &lt;code&gt;Left&lt;/code&gt; part of the code).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Milkis as M
import Effect.Aff (Aff, attempt)

getTokenCredentialsStr :: String -&amp;gt; Aff (Either String String)
getTokenCredentialsStr basicAuthorizationStr = do
    let
      opts =
        { body: "grant_type=client_credentials"
        , method: M.postMethod
        , headers: M.makeHeaders { "Authorization": basicAuthorizationStr
                                 , "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
                                 }

        }
    _response &amp;lt;- attempt $ fetch (M.URL "https://api.twitter.com/oauth2/token") opts
    case _response of
      Left e -&amp;gt; do
        pure (Left $ show e)
      Right response -&amp;gt; do
        theText &amp;lt;- M.text response
        pure (Right theText)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to bring it all together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
type BearerAuthorization =
  { token_type :: String
  , access_token :: String
  }

basicHeader :: String -&amp;gt; String
basicHeader base64EncodedStr = "Basic " &amp;lt;&amp;gt; base64EncodedStr

toBearerAuthorization :: String -&amp;gt; Either String BearerAuthorization
toBearerAuthorization tokenString = do
  case SimpleJSON.readJSON tokenString of
    Left e -&amp;gt; do
      Left $ show e
    Right (result :: BearerAuthorization) -&amp;gt; do
      Right result

getTokenCredentials :: TwitterCredentials -&amp;gt; Aff (Either String BearerAuthorization)
getTokenCredentials credentials = do
  tokenCredentialsStrE &amp;lt;- getTokenCredentialsStr $ basicHeader $ authorizationStr credentials
  case tokenCredentialsStrE of
    Left error -&amp;gt; do
      pure (Left error)
    Right tokenCredentialsStr -&amp;gt; do
      let tokenCredentialsE = toBearerAuthorization(tokenCredentialsStr)
      case tokenCredentialsE of
        Left error -&amp;gt; do
          pure (Left error)
        Right authResult -&amp;gt; do
          pure (Right authResult)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, we had the bearer token. It's finally time to search for &lt;code&gt;Kim Kardashian&lt;/code&gt;!&lt;br&gt;
PureScript had this interesting signature format though. What it was saying below was that &lt;code&gt;showResults&lt;/code&gt; took as input a &lt;code&gt;BearerAuthorization&lt;/code&gt; and a &lt;code&gt;String&lt;/code&gt; and returned an &lt;code&gt;Aff (Either String SearchResults)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Also, the &lt;code&gt;SearchResults&lt;/code&gt; and &lt;code&gt;Status&lt;/code&gt; had lots of fields but she just wanted the basic stuff.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
type Status =
  { created_at :: String
  , id_str :: String
  , text :: String
  }

type SearchResults =
  { statuses :: Array Status
  }

twitterURL :: String -&amp;gt; M.URL
twitterURL singleSearchTerm = M.URL $ "https://api.twitter.com/1.1/search/tweets.json?q=" &amp;lt;&amp;gt; singleSearchTerm

showResults :: BearerAuthorization -&amp;gt; String -&amp;gt; Aff (Either String SearchResults)
showResults credentials singleSearchTerm = do
  let
    opts =
      { method: M.getMethod
      , headers: M.makeHeaders { "Authorization": "Bearer " &amp;lt;&amp;gt; credentials.access_token}

      }
  _response &amp;lt;- attempt $ fetch (twitterURL singleSearchTerm) opts
  case _response of
    Left e -&amp;gt; do
      pure (Left $ show e)
    Right response -&amp;gt; do
      stuff &amp;lt;- M.text response
      let aJson = SimpleJSON.readJSON stuff
      case  aJson of
        Left e -&amp;gt; do
          pure $ Left $ show e
        Right (result :: SearchResults) -&amp;gt; do
          pure (Right result)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, reaching the very end to the &lt;code&gt;main&lt;/code&gt; command!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Effect.Class.Console (errorShow, log)
import Effect.Aff (Aff, launchAff_)

main :: Effect Unit
main = launchAff_ do
  let searchTerm = "Kim Kardashian"
  config &amp;lt;- readConfig "./config/twitter_credentials.json"
  case config of
    Left errorStr -&amp;gt; errorShow errorStr
    Right credentials -&amp;gt; do
      tokenCredentialsE &amp;lt;- getTokenCredentials credentials
      case tokenCredentialsE of
        Left error -&amp;gt;
          errorShow error
        Right tokenCredentials -&amp;gt; do
          resultsE &amp;lt;- showResults tokenCredentials searchTerm
          case resultsE of
            Left error -&amp;gt;
              errorShow error
            Right result -&amp;gt;
              log $ show $ "Response:" &amp;lt;&amp;gt; (show result.statuses)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;launchAff_&lt;/code&gt; was required because the entire computation returned &lt;code&gt;Aff something&lt;/code&gt; but &lt;code&gt;main&lt;/code&gt; was of type &lt;code&gt;Effect Unit&lt;/code&gt;. So &lt;code&gt;launchAff_&lt;/code&gt; just converted &lt;code&gt;Aff something&lt;/code&gt; to &lt;code&gt;Effect Unit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As Kim beamed with pride at her code, she flashed her eyes at Kanye and asked him, "Isn't the code beautiful?"&lt;/p&gt;

&lt;p&gt;Kanye gazed into her eyes and said, "Actually, it sucks. There are so many case statements in that code that I feel cross eyed."&lt;/p&gt;

&lt;p&gt;And the next thing Kanye knew, was that he was flat on the ground, his jaw felt like it had been displaced and he was seeing double.&lt;/p&gt;

&lt;p&gt;For there are three things you don't tell your wife:&lt;/p&gt;

&lt;p&gt;1) Honey, you have gained weight&lt;br&gt;
2) Your code sucks&lt;br&gt;
3) I miss my mother's cooking.&lt;/p&gt;

&lt;p&gt;As Kanye massaged his jaw, he muttered, ".. I guess she does not want to know about the &lt;code&gt;ExceptT&lt;/code&gt; Monad.."&lt;/p&gt;

</description>
      <category>functional</category>
      <category>purescript</category>
    </item>
    <item>
      <title>PureScript on AWS Lambda: Using Express and Serverless</title>
      <dc:creator>Rajiv Abraham</dc:creator>
      <pubDate>Tue, 31 Mar 2020 15:15:30 +0000</pubDate>
      <link>https://dev.to/rabraham/purescript-on-aws-lambda-using-express-and-serverless-gm9</link>
      <guid>https://dev.to/rabraham/purescript-on-aws-lambda-using-express-and-serverless-gm9</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is an ported, edited version of the &lt;a href="https://medium.com/@rajiv.abraham/purescript-on-aws-lambda-7cf04bbcc25e"&gt;original&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Purpose
&lt;/h3&gt;

&lt;p&gt;This post shows you how to run PureScript 0.12 on AWS Lambda, using &lt;a href="https://expressjs.com/"&gt;Express&lt;/a&gt; on the &lt;a href="https://serverless.com/"&gt;Serverless&lt;/a&gt; platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;The final output of this article is also a &lt;a href="https://github.com/RAbraham/hello-purescript-serverless"&gt;repo&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites.
&lt;/h3&gt;

&lt;p&gt;You should have nodejs (i.e. nvm, npm) setup on your machine, preferably 8.10. AWS Lambda uses 8.10. I’m new to nodejs land but I’m guessing that higher minor versions should be ok.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Setup
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g purescript
npm install -g pulp bower
npm install -g serverless
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  AWS Credentials
&lt;/h3&gt;

&lt;p&gt;If you haven’t already, generate an AWS key and secret. This user must have AdministratorAccess permissions. Here are the &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey_CLIAPI"&gt;docs&lt;/a&gt; or a slightly outdated &lt;a href="https://www.youtube.com/watch?v=HSd9uYj2LJA"&gt;video&lt;/a&gt;. For the video, follow on to 1:40 and ignore the Serverless Dashboard instructions(around 0:58 to 1:00), we are going to do that on the command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless config credentials --provider aws --key your-aws-key --secret your-aws-secret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Project Setup
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir hello-purescript-serverless
cd hello-purescript-serverless
npm init # fill in as directed
pulp init
pulp build

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If all goes well, you should see something like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* Building project in /Users/rabraham/Documents/dev/purescript/hello-purescript-serverless
Compiling Data.Symbol
Compiling Type.Data.RowList
...
Compiling Main
Compiling PSCI.Support
Compiling Effect.Class.Console
* Build successful.

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now let’s install our project specific packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bower install --save purescript-aws-lambda-express purescript-express
npm install --save aws-serverless-express express
npm install serverless-offline --save-dev

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;purescript-express is a wrapper on express while purescript-aws-lambda-express provides the wrapper for AWS Lambda. serverless-offline allows us to test the code locally before deploying it to AWS Lambda.&lt;/p&gt;

&lt;p&gt;At time of writing, purescript-express has an issue where we have to install the following two packages too. Try a &lt;code&gt;pulp build&lt;/code&gt; right now and if that fails, run the following commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bower install --save purescript-test-unit
bower install --save purescript-aff

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s build it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pulp build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should see some warnings but at the end, you should see &lt;code&gt;* Build successful&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main Course
&lt;/h3&gt;

&lt;p&gt;In your &lt;code&gt;src/Main.purs&lt;/code&gt;, delete the previous code and paste the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module Main where

import Node.Express.App (App, get)
import Node.Express.Handler (Handler)
import Node.Express.Response (sendJson)
import Network.AWS.Lambda.Express as Lambda

-- Define an Express web app

indexHandler :: Handler
indexHandler = do
  sendJson { status: "ok" }

app :: App
app = do
  get "/" indexHandler

-- Define the AWS Lambda handler

handler :: Lambda.HttpHandler
handler =
  Lambda.makeHandler app

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Build Your App&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pulp build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Serverless Setup
&lt;/h3&gt;

&lt;p&gt;In the root of your project, create the file &lt;code&gt;serverless.yml&lt;/code&gt; and paste the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;purescript-aws-lambda-express-test&lt;/span&gt;

&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws&lt;/span&gt;
  &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodejs8.10&lt;/span&gt;
  &lt;span class="na"&gt;memorySize&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;128&lt;/span&gt;
  &lt;span class="c1"&gt;# stage: ${opt:stage dev}&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;

&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;lambda&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;output/Main/index.handler&lt;/span&gt;
    &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# this matches the base path&lt;/span&gt;
          &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ANY&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/{any+}&lt;/span&gt;
          &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ANY&lt;/span&gt;

&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless-offline&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s test this locally: On one terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless offline start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Open another terminal and do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should see &lt;code&gt;{"status":"ok"}&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy
&lt;/h3&gt;

&lt;p&gt;Once it works locally, let’s deploy to AWS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless deploy -v
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output should look like something below. Note, your endpoint will be different:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Serverless: Packaging service
...
Service Information
service: purescript-aws-lambda-express-test
stage: dev
region: us-east-1
...
Stack Outputs
...
ServiceEndpoint: https://l4qajv7v95.execute-api.us-east-1.amazonaws.com/dev
....

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Copy the link shown as &lt;code&gt;ServiceEndpoint&lt;/code&gt; and you know what to do!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://l4qajv7v95.execute-api.us-east-1.amazonaws.com/dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"status":"ok"}%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Undeploy
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless remove -v
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I hope this enables you to make PureScript web applications! Thanks to &lt;a href="https://github.com/nkly/purescript-express"&gt;purescript-express&lt;/a&gt; and &lt;a href="https://github.com/lpil/purescript-aws-lambda-express"&gt;purescript-aws-lambda-express&lt;/a&gt; for making this possible.&lt;/p&gt;

</description>
      <category>purescript</category>
      <category>functional</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Reading code easily with immutable values(Pyrsistent).</title>
      <dc:creator>Rajiv Abraham</dc:creator>
      <pubDate>Mon, 23 Mar 2020 01:59:52 +0000</pubDate>
      <link>https://dev.to/rabraham/reading-code-easily-with-immutable-values-pyrsistent-33eh</link>
      <guid>https://dev.to/rabraham/reading-code-easily-with-immutable-values-pyrsistent-33eh</guid>
      <description>&lt;h6&gt;
  
  
  TLDR:
&lt;/h6&gt;

&lt;p&gt;Use data structures that don't change once created(using Pyrsistent) to make it easy to understand and maintain code.&lt;/p&gt;

&lt;h4&gt;
  
  
  Purpose.
&lt;/h4&gt;

&lt;p&gt;When a data structure(e.g. dict) once created, does not change, it allows us to read code with more confidence.&lt;/p&gt;

&lt;p&gt;For e.g. Let's say you have a &lt;code&gt;customer&lt;/code&gt; variable in your code and you are tracking it's value by reading the code. What do you reason is the value of &lt;code&gt;customer&lt;/code&gt; below?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Rajiv"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;some_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the above code, we can't say. In Python, for most default data structures like &lt;code&gt;dict&lt;/code&gt;,  it is possible that &lt;code&gt;some_function&lt;/code&gt; could have changed the value of &lt;code&gt;customer&lt;/code&gt;. So, we have to dig in and read the code of &lt;code&gt;some_function&lt;/code&gt; to be fully sure. If the code of &lt;code&gt;some_function&lt;/code&gt; was below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
    &lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'NewRajiv'&lt;/span&gt; &lt;span class="c1"&gt;# Changing the values. blasphemy
&lt;/span&gt;    &lt;span class="c1"&gt;# do something with a1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;then &lt;code&gt;print(customer)&lt;/code&gt; would display &lt;code&gt;{'name': 'NewRajiv', 'age': 40}&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If you are lucky, &lt;code&gt;some_function&lt;/code&gt; does not pass it forward to other functions! Or else, you would have to dig in and read those functions too :). Now that would suck. Unless, it is the intention that the &lt;code&gt;customer&lt;/code&gt; field should be mutated but in most cases, one does not expect it to be so(in other languages,naming conventions are used to indicate if that is the case).  A knowledgeable programmer may make a copy(via the &lt;code&gt;copy.deepcopy()&lt;/code&gt;) and work on the copy to prevent her code from affecting the client code but I have not been that  knowledgeable programmer :) &lt;/p&gt;

&lt;p&gt;What if we could use a data structure that once created, cannot be changed i.e. it is immutable. Let's check out a library called &lt;a href="https://github.com/tobgu/pyrsistent"&gt;pyrsistent&lt;/a&gt; that gives us such data structures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pyrsistent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="c1"&gt;# m is like a dictionary
&lt;/span&gt;
&lt;span class="n"&gt;customer1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'Rajiv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;customer2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customer1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'NewRajiv'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# pmap({'age': 40, 'name': 'Rajiv'})
&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# pmap({'age': 40, 'name': 'NewRajiv'})
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When we specify a different value('NewRajiv'), a copy is created with that new value and assigned to &lt;code&gt;customer2&lt;/code&gt;. &lt;code&gt;customer1&lt;/code&gt; still retains the value it was first assigned. Now, let's go back to our previous code example and modify it a bit for &lt;code&gt;pyrsistent&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pyrsistent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="c1"&gt;# m is like a dictionary
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'NewRajiv'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# do something with a1 
&lt;/span&gt;
&lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Rajiv"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;some_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&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;print(customer)&lt;/code&gt; would display &lt;code&gt;{'name': 'Rajiv', 'age': 40}&lt;/code&gt;, the value set in our code. So, we can safely reason about our code and what it's doing without worrying about it changing inside &lt;code&gt;some_function&lt;/code&gt;. We don't have to even look into &lt;code&gt;some_function&lt;/code&gt; in this case. Trust me, when you can't run that snippet of code to see what the actual values are, this feature makes life so easy :).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pyrsistent&lt;/code&gt; also has support for other common data structures(i.e. lists, sets) and much much more. Most of these &lt;code&gt;pyrsistent&lt;/code&gt; data structures are drop in replacements for their Python counterparts when it comes to accessing the data.&lt;/p&gt;

&lt;p&gt;From the pyrsistent docs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pyrsistent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;  &lt;span class="c1"&gt;# like a list
&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&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="c1"&gt;# 2
&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# pvector([2, 3])
&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# [2, 4, 6, 8]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  On Speed and Memory
&lt;/h3&gt;

&lt;p&gt;I simplified(ok, I lied) when I said that &lt;code&gt;pyrsistent&lt;/code&gt; makes a copy of the data structure. Such a practice would be a waste of memory and time if we copy over every huge data structure. &lt;code&gt;pyrsistent&lt;/code&gt; mitigates that to a great extent by not just blindly copying data structures and then making the modifications. It tries to be intelligent by &lt;code&gt;sharing the common parts&lt;/code&gt; between a original data structure and the new modified copy to save on memory and time.&lt;/p&gt;

&lt;p&gt;Let's take an example(Credit: Wikipedia: Persistent Data Structures). Ah, you now are exposed to what this is really called.  This concept is called &lt;code&gt;persistent data structures&lt;/code&gt; or &lt;code&gt;functional data structures&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;NOTE: The below example is just to explain the concepts and such a binary search tree is not part of &lt;code&gt;pyrsistent&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Let's say you had a binary search tree(&lt;code&gt;xs&lt;/code&gt;) which was a persistent data structure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zB3Xc8Xd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Purely_functional_tree_before.svg/696px-Purely_functional_tree_before.svg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zB3Xc8Xd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Purely_functional_tree_before.svg/696px-Purely_functional_tree_before.svg.png" alt="alt text" title="Binary Search Tree"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now if you added a node &lt;code&gt;e&lt;/code&gt; to that data structure, e.g. &lt;code&gt;ys = insertNode(xs, e)&lt;/code&gt; A naive implementation would copy the data structure and then insert &lt;code&gt;e&lt;/code&gt; at the appropriate location. In a persistent data structure approach, it would be:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dR4UNBS5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Purely_functional_tree_after.svg/876px-Purely_functional_tree_after.svg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dR4UNBS5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Purely_functional_tree_after.svg/876px-Purely_functional_tree_after.svg.png" alt="alt text" title="Persistent Binary Search Tree"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;e&lt;/code&gt; falls into the right side of the tree(i.e. the tree with &lt;code&gt;g&lt;/code&gt; as the root), the tree with root &lt;code&gt;b&lt;/code&gt; is not affected and hence can be reused. You can see a arrow from &lt;code&gt;d'&lt;/code&gt;  to &lt;code&gt;b&lt;/code&gt; indicating that.&lt;/p&gt;

&lt;p&gt;This reuse saves memory space, and saves time not done copying as it merely uses pointers to refer to the unchanged data.&lt;/p&gt;

&lt;p&gt;Note: just because a data structure is being reused does not mean modifications to one can affect another. They are immutable and hence cannot be modified. If you do modify, a new structure is created like above.&lt;/p&gt;

&lt;p&gt;Note on Note: &lt;code&gt;pyrsistent&lt;/code&gt; tries to be as fast as possible and has comparable speeds to the norm for most cases. The complexity of most operations are well described in their docs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nested Transformations
&lt;/h3&gt;

&lt;p&gt;What if we have to update a nested value in a data structure while maintaining immutability. &lt;code&gt;pyrsistent&lt;/code&gt; has a method &lt;code&gt;transform&lt;/code&gt; for that. &lt;br&gt;
How I would normally do it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;copy&lt;/span&gt;
&lt;span class="n"&gt;m4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# I want to update c[1] to 17
&lt;/span&gt;&lt;span class="n"&gt;m4_new&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deepcopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="n"&gt;m4_new&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'c'&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="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;From their docs,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pyrsistent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;  &lt;span class="c1"&gt;# m is like a dictionary
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pyrsistent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="c1"&gt;# m is like a list
&lt;/span&gt;&lt;span class="n"&gt;m4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&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="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;v&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;m4_new&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;'c'&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="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m4_new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# pmap({'a': 5, 'c': pvector([1, 17]), 'b': 6})
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Updating dictionaries
&lt;/h3&gt;

&lt;p&gt;One thing I do very often is merging dictionaries. For e.g., I may have to construct my configuration taking the the following sources with the earliest being the highest priority.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;li&gt;File configuration&lt;/li&gt;
&lt;li&gt;Default configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How I would normally do it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;default_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;database_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'dev_url'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'postgres'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Imagine file_conf below was extracted from a file
&lt;/span&gt;&lt;span class="n"&gt;file_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'test_user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5433&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Imagine env_conf below was constructed from environment variables
&lt;/span&gt;&lt;span class="n"&gt;environment_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;database_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'test_url'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;final_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;default_conf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;file_conf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;environment_conf&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final_conf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# {'database_url': 'test_url', 'user': 'test_user', 'port': 5433}
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's great for 99% of the cases I would think :). But for the sake of discussion, perhaps if you had HUGE dictionaries(e.g. merging all the data you scrapped illegally from some website ;) ), that would be some duplication of data in memory.&lt;br&gt;
In &lt;code&gt;pyrsistent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pyrsistent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="n"&gt;default_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;database_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'dev_url'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'postgres'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Imagine file_conf below was extracted from a file
&lt;/span&gt;&lt;span class="n"&gt;file_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'test_user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5433&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Imagine env_conf below was constructed from environment variables
&lt;/span&gt;&lt;span class="n"&gt;environment_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;database_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'test_url'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;final_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;default_conf&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file_conf&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;environment_conf&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final_conf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# pmap({'database_url': 'test_url', 'user': 'test_user', 'port': 5433})
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I hope this is enough to get you started in a better coding experience :). There are many other wonderful features in &lt;code&gt;pyrsistent&lt;/code&gt; like having the above behaviour for records(&lt;code&gt;PRrecord&lt;/code&gt;) and clases(&lt;code&gt;PClass&lt;/code&gt;) and many more advanced features. I'll leave that for another post.&lt;/p&gt;

&lt;p&gt;So head out to  &lt;a href="https://github.com/tobgu/pyrsistent"&gt;pyrsistent&lt;/a&gt; and check it out. And if you like it, don't forget to star! It's a wonderful piece of engineering whose authors that we should applaud and support.&lt;/p&gt;

</description>
      <category>functional</category>
      <category>python</category>
    </item>
    <item>
      <title>Introduction to Datalog(Bashlog) in Python</title>
      <dc:creator>Rajiv Abraham</dc:creator>
      <pubDate>Sun, 16 Feb 2020 06:27:18 +0000</pubDate>
      <link>https://dev.to/rabraham/introduction-to-datalog-bashlog-in-python-1a38</link>
      <guid>https://dev.to/rabraham/introduction-to-datalog-bashlog-in-python-1a38</guid>
      <description>&lt;h6&gt;
  
  
  TLDR:
&lt;/h6&gt;

&lt;p&gt;Datalog is like SQL + Recursion. It's derivatives have reduced the code base by 50% or more.&lt;/p&gt;

&lt;h4&gt;
  
  
  Datalog
&lt;/h4&gt;

&lt;p&gt;Today, I would like to explore a constrained  language called Datalog. It's a constrained form of Prolog and may not be as expressive as C++ or Python. But it's derivatives have been known to reduce the numbers of lines of code down by 50% or more(&lt;a href="https://dl.acm.org/citation.cfm?id=1755913.1755937"&gt;Overlog&lt;/a&gt;, &lt;a href="https://storage.googleapis.com/pub-tools-public-publication-data/pdf/43462.pdf"&gt;Yedalog&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Let's get started:&lt;/p&gt;

&lt;p&gt;Datalog has a &lt;em&gt;minimalist syntax&lt;/em&gt; which I love. Let's take an example.&lt;br&gt;
Suppose our data is about fathers and sons, mothers and daughters. If we had an excel sheet, we would enter the data like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Father  Son
Aks     Bob
Bob     Cad
Yan     Zer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and another excel sheet for mothers and daughters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mother  Daughter
Mary    Marla
Marla   Kay
Jane    Zanu
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In Datalog, we express the same data as(together):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;father('Aks', 'Bob')
father('Bob', 'Cad')
father('Yan', 'Zer')
mother('Mary', 'Marla')
mother('Marla', 'Kay')
mother('Jane', 'Zanu')
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here we are trying to say Aks is the father of 'Bob' and 'Bob' is the father of 'Cad'. The datum father('Aks', 'Bob') is called a &lt;em&gt;&lt;strong&gt;fact&lt;/strong&gt;&lt;/em&gt; i.e. it is true.&lt;/p&gt;

&lt;p&gt;So Datalog can be used to express data. Not very interesting so far but a building block. These facts above can also be viewed as the existing state of the system, like we store state in files, or databases.&lt;/p&gt;

&lt;p&gt;But that's not enough. What about code? For Datalog, code are specified as &lt;em&gt;&lt;em&gt;rules&lt;/em&gt;&lt;/em&gt; to be applied declaratively.&lt;/p&gt;

&lt;p&gt;Let's say our program needs to find out who's a grandfather. We could write a rule like:&lt;br&gt;
'A person X is the grandfather of Z if X is the father of Y and Y is the father of Z'. In Datalog, this rule is written as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grandfather(X, Z) :- father(X,Y), father(Y, Z)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The LHS (i.e. grandfather) is known as the &lt;code&gt;head&lt;/code&gt; and the RHS after the &lt;code&gt;:-&lt;/code&gt; is known as the body&lt;/p&gt;

&lt;p&gt;X, Y, Z are special variables called logic variables. They are different from regular variables. They are more used to represent a pattern or to link the head and the body.&lt;/p&gt;

&lt;p&gt;To further understand logical variables, consider these two rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;grandfather&lt;span class="o"&gt;(&lt;/span&gt;X, Z&lt;span class="o"&gt;)&lt;/span&gt; :- father&lt;span class="o"&gt;(&lt;/span&gt;X,Y&lt;span class="o"&gt;)&lt;/span&gt;, father&lt;span class="o"&gt;(&lt;/span&gt;Y, Z&lt;span class="o"&gt;)&lt;/span&gt;
grandmother&lt;span class="o"&gt;(&lt;/span&gt;X, Z&lt;span class="o"&gt;)&lt;/span&gt; :- mother&lt;span class="o"&gt;(&lt;/span&gt;X,Y&lt;span class="o"&gt;)&lt;/span&gt;, mother&lt;span class="o"&gt;(&lt;/span&gt;Y, Z&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here the &lt;code&gt;X&lt;/code&gt;, &lt;code&gt;Z&lt;/code&gt; and &lt;code&gt;Y&lt;/code&gt; used in &lt;code&gt;grandfather&lt;/code&gt; are completely different from the &lt;code&gt;X&lt;/code&gt;, &lt;code&gt;Y&lt;/code&gt; and &lt;code&gt;Z&lt;/code&gt; in &lt;code&gt;grandmother&lt;/code&gt;. In rules, the variables only make sense &lt;code&gt;in&lt;/code&gt; that single rule. So we can reuse the same logic variables in different rules without worrying that they have some logical connection.&lt;/p&gt;

&lt;p&gt;The next concept is &lt;em&gt;&lt;em&gt;queries&lt;/em&gt;&lt;/em&gt;. How do we feed input and get back some output. &lt;br&gt;
Queries are similar to rules but without a head.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;father&lt;span class="o"&gt;(&lt;/span&gt;X, &lt;span class="s1"&gt;'Aks'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;, mother&lt;span class="o"&gt;(&lt;/span&gt;Z, &lt;span class="s1"&gt;'Aks'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;we mean, find the mother and father of 'Aks'&lt;br&gt;
or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;father&lt;span class="o"&gt;(&lt;/span&gt;X, &lt;span class="s1"&gt;'Raj'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;, mother&lt;span class="o"&gt;(&lt;/span&gt;Z, &lt;span class="s1"&gt;'Raj'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;we mean, find the father and mother of 'Raj'&lt;/p&gt;

&lt;p&gt;Suppose, we want to say find the mother and father of all the children in the database, we make the query&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;father&lt;span class="o"&gt;(&lt;/span&gt;X, Y&lt;span class="o"&gt;)&lt;/span&gt;, mother&lt;span class="o"&gt;(&lt;/span&gt;Z, Y&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Datalog will link &lt;code&gt;Y&lt;/code&gt; for all &lt;code&gt;mother&lt;/code&gt; and &lt;code&gt;father&lt;/code&gt; facts and find the mothers and fathers for a child. It will not mix up fathers and mothers :)&lt;/p&gt;

&lt;p&gt;Now, If you opened a datalog interpreter and fed the above and made the following queries, you would get the results shown after the # sign&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;father(X,_) # ['Aks', 'Bob', 'Yan']
father(_,X) # ['Bob', 'Cad', 'Zer']
father(X, Y) # [('Aks', 'Bob'), ('Bob', 'Cad'), ('Yan', 'Zer')
father(X, 'Zer'), father('Zer', Y) # [] as there are no facts that match the query
grandfather(X, Y) # [('Aks', 'Cad')]
grandfather(X,_) # ['Aks']
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here '_' is a special variable indicating that you don't care for the result.&lt;/p&gt;

&lt;p&gt;I was always interested in the Datalog syntax and it's power. I kept delaying it until I met &lt;a href="https://github.com/thomasrebele/bashlog"&gt;Bashlog&lt;/a&gt;. Because, the &lt;em&gt;syntax of datalog is so simple&lt;/em&gt;, it makes it &lt;em&gt;easy to write interpeters&lt;/em&gt; for different targets. What Bashlog did was take Datalog syntax and convert it to bash scripts! Because, it used awk(mawk actually), sed, grep, which are tuned for high performance on Unix like platforms, it was incredibly fast in parsing big text files, comparable with all the specialized databases out there. &lt;strong&gt;Just Bash Scripts&lt;/strong&gt;. It blew my mind. So if you are interested in pure Datalog, check out Bashlog&lt;/p&gt;

&lt;p&gt;With Bashlog, you can run any bash like command and read that using Bashlog. Imagine there was a file('~/data.tsv') with tab separated values of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;Aks Bob
Bob Cad
Yan Zer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We could read that data like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;facts&lt;span class="o"&gt;(&lt;/span&gt;F, S&lt;span class="o"&gt;)&lt;/span&gt; :~ &lt;span class="nb"&gt;cat&lt;/span&gt; ~/data.tsv
father&lt;span class="o"&gt;(&lt;/span&gt;X, Y&lt;span class="o"&gt;)&lt;/span&gt; :- facts&lt;span class="o"&gt;(&lt;/span&gt;X, Y&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then we proceed the same manner like before. What's awesome is that you can run any Unix command(e.g. &lt;code&gt;ls -l&lt;/code&gt;) as long as it returns an output of tab separated values.&lt;/p&gt;

&lt;p&gt;But I wanted to  use Datalog in my day to day programming. I wanted to see if I could use and leverage Datalog along with Python. Some benefits of Datalog in Python are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modularity. How do we abstract out patterns in our rules and facts.&lt;/li&gt;
&lt;li&gt;Possible access to exisitng rich source of libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built &lt;a href="https://github.com/RAbraham/mercylog"&gt;Mercylog&lt;/a&gt; in Python. &lt;/p&gt;

&lt;p&gt;So let's translate the above rules to Mercylog syntax.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;If you are using the Bashlog variant,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;then you need Java 8 already installed
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/RAbraham/mercylog_tutorial.git
&lt;span class="nb"&gt;cd &lt;/span&gt;mercylog_tutorial
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
python tutorial.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That should print&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Aks'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Mary'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Read below on the explanation and make tweaks if you want and run &lt;code&gt;python tutorial.py&lt;/code&gt; again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mercylog&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mercylog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BashlogV1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# father('Aks', 'Bob')
# father('Bob', 'Cad')
# father('Yan', 'Zer')
# mother('Mary', 'Marla')
# mother('Marla', 'Kay')
# mother('Jane', 'Zanu')
&lt;/span&gt;
&lt;span class="n"&gt;father&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'father'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mother&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'mother'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;facts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Aks'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Cad'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Yan'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Zer'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;mother&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Mary'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Marla'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;mother&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Marla'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Kay'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;mother&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Jane'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Zanu'&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;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# grandfather(X, Z) :- father(X,Y), father(Y, Z)
&lt;/span&gt;&lt;span class="n"&gt;grandfather&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'grandfather'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'X'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Y'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Z'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="n"&gt;grandfather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;While in Datalog, you don't have to explicitly state the variables and the relation, as it is baked in to the language,  in our library in Python, we need to (e.g. X, Y, Z and father, grandfather)&lt;/p&gt;

&lt;p&gt;Making a query in python has the following syntax&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A concrete example would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grandfather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# which gives [('Aks', 'Cad')]
&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# ['Aks', 'Bob', 'Yan']
&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# ['Bob', 'Cad', 'Zer']
&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# [('Aks', 'Bob'), ('Bob', 'Cad'), ('Yan', 'Zer')
&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;granfather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# ['Aks']
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Creating this DSL in python gives us some unique benefits. For e.g if we had these two relations&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;paternal_grandfather&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'paternal_grandfather'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;maternal_grandmother&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'maternal_grandmother'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;father&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'father'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mother&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'mother'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'X'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Y'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Z'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;rules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;paternal_grandfather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="n"&gt;maternal_grandmother&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mother&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;mother&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&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 you notice, the rule for &lt;code&gt;paternal_grandfather&lt;/code&gt; and &lt;code&gt;maternal_grandmother&lt;/code&gt; are very similar. I could perhaps encapsulate that into a function. I'll use the word &lt;code&gt;transitive&lt;/code&gt; though I believe it is incorrect to use it.. but I don't know what to call this for now. Rewriting the above code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;transitive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clause&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'X'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Y'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Z'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clause&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;clause&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;paternal_grandfather&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'paternal_grandfather'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;maternal_grandmother&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'maternal_grandmother'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;father&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'father'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mother&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'mother'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;rules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;transitive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paternal_grandfather&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;father&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;transitive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maternal_grandmother&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mother&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;In this way, using Python, we have modularized a pattern using the &lt;code&gt;transitive&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Let's recap the benefits of Mercylog&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple Syntax. All you need to know is facts and rules. Because of such simplicity, it is also easy to build compilers for it.&lt;/li&gt;
&lt;li&gt;Expressive. Rules give a powerful mechanism &lt;/li&gt;
&lt;li&gt;Declarative. Like SQL but more expressive. So we can optimize it's engines without affecting the code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll continue to update you with my future learnings!&lt;/p&gt;

</description>
      <category>datalog</category>
      <category>python</category>
    </item>
  </channel>
</rss>
