How can pure functions represent state change?

Pure functions have no effect besides returning an immutable value. If that’s true, then how can we use them to represent changing state?

Transcript

Eric Normand: If our functions are pure, meaning they don’t change anything outside of their scope, then how is it that we can use functions to represent change and to represent behaviors? Change over time?

Hi. My name is Eric Normand, and these are my thoughts on functional programming. Let’s imagine that we’re already good at making pure functions, doing a lot of work on our calculations.

We’re good at making pipelines, all that in-the-weeds functional programming stuff. Very important, but let’s say we’re already good at it. Why are we even using functions? What can we do with these functions now that we’re good at them? My answer is that we should be modeling behavior with functions. Let’s back up a step.

When I was younger, less experienced at programming, and first introduced to Java, if one of the requirements said that, “Well, this thing needs to be able to change over time,” I would probably just have made a setter method for that thing and just said, “Well, this is how you change it. You call this method, and it will mutate this value. It will just set it to something else.”

I think that that is about as much analysis as I ever did with what it means to change. I don’t think I’m alone in that because I hear people all the time asking like, “Isn’t the world mutable? Don’t we need mutable state? Because the world is mutable, how can you model things when things change? You need changeable things.”

I think that that misses the point. The point is this. If you just say, “Things change,” you haven’t really captured anything interesting. You haven’t said anything specific about how they change. When do they change? Why do they change?

You have this situation where we’ve got this general memory where a byte can take on any value between 0 and 255 that you want to put in there. You’re not constraining it at all based on the semantics, based on your domain, based on what you want that byte to represent.

What functions can let you do is define how things change. How do they do that? One way is because functions take an argument and they return a return value. We’re talking about pure functions right now.

They have an input and an output. They don’t change their input. We’re just not dealing with any mutation at all, pure functions. If you make that input the current state, the current value of the thing, you can make the output the next value of the thing.

You’re defining how it changes very precisely. It goes from this current thing to this new thing. Now, you can add another argument and do something like make that argument an event.

You say, “Well, when the state is like this and we get this event, then what is the output? What is the new state?” Or maybe it’s, “What is the new state?” You also turn another set of events that get called. They get dispatched.

This is the kind of modeling that we’re able to do in functional programming, is take this top-down approach of saying how the entire state changes based on the events we’re getting.

You’re defining it in such a way that it’s totally testable. You don’t have to set anything up. You just pass in a current state and an event, and you can test properties of the return value.

There’s nothing like, “Do I have to make a new mutable thing and like fiddle with its methods until it gets to the right state, and then test this one new method, and then check if it changed?”

It’s much more testable, but then there’s this other thing. There are so many questions and so many ways of thinking that mutation just doesn’t really allow us to do. You have to do a lot of work to work around.

One of those — I think it’s the best example — is to think about counterfactuals. Let’s say, we do have a real current state. This is the state of the system. The state of whatever thing, entity we’re representing, whatever it is.

We want to ask, “What would this thing look like after I receive this event? I haven’t received it, but what would it look like if I did?” That’s a lot like what a test is. It’s a counterfactual.

It’s not an actual production data. It’s not an actual production event, but we’re asking, “What happens in the system when I do this, and I expect it to look like this?” It’s a test. It’s often also very useful in your production system.

What would happen if I sent it 10,000 of these events? Would it overflow? One thing I did as an example is I had a state of the current screen. This is all the information you need for the screen, including the title of that screen and what back button to have on the top.

How did I figure out what label the back button would have? It didn’t just say back. It had the title of the previous screen. I actually ran the behavior function with the current screen and the back button event.

Then I would get back the next screen, which was the new screen, which was the back screen. I didn’t change the actual screen. It’s just the state. Then I can read off the title from there.

These are the things that become just easy when you’re dealing with pure functions. You’ve defined your behavior in your functions. You can imagine me doing it a different way, which would be the current screen has a mutable field called title. It has a mutable field called back button label.

I would have to go and set them manually from somewhere else and rely on the sequence of steps that got me there to calculate what each one should be. As opposed to representing the entire thing as data and then a behavior function.

This is the thing I’m working on for the book. I’ve been talking with my editor about not…I don’t want to reproduce a lot of the work out there. There’s a lot of good work actually on the functional programming in the small like how to do currying, how to make data transformation pipelines, map, filter, reduce, all those things.

Avoid getting down in the weeds there, but then what is there to talk about? I think it’s this kind of stuff. I’ve been reading books. No one is talking about using functions to model the behavior, which is something we do. It’s not like I’m making it up, but I’ve got a grip on it. I think it’s high-level enough to fit right in the book.

My name is Eric Normand. This is “Thoughts on Functional Programming.” If you want to get in touch with me, I love hearing from my listeners, answering questions. I’m @ericnormand on Twitter. You can also reach me over email, eric@lispcast.com. See you later.

The post How can pure functions represent state change? appeared first on LispCast.

Permalink

And now we're juxt'n...

4clojure 27 - Palindrome Detector

Palindrome

Write a function which returns true if the given sequence is a palindrome.

Hint: "racecar" does not equal '(\r \a \c \e \c \a \r).

Unit tests

We'll start by setting up a placeholder function and our test suite in a KLIPSE snippet. This code is live and editable, so go ahead and fill it in to make the tests pass. Or not... Not trying to tell you what to do or anything...

(ns live.test
  (:require [cljs.test :refer-macros [deftest is testing run-tests]]))

(defn palindrome? [s]
  )

(deftest test-27
  (is (false? (palindrome? '(1 2 3 4 5))))
  (is (true? (palindrome? "racecar")))
  (is (true? (palindrome? [:foo :bar :foo])))
  (is (true? (palindrome? '(1 1 3 3 1 1))))
  (is (false? (palindrome? '(:a :b :c)))))

(run-tests)

First off, here's the standard, boring way to do it:

(#(= (seq %) (reverse %)) '(1 2 3 4 5))
(#(= (seq %) (reverse %)) '(1 2 3 2 1))

But friends don't let friends pass up a juxt-ortunity...

Are you ready for this?

Remember, juxt is our universal vector constructor. So, what do we want in our vector?

Let's back up a tiny bit - were it not for that pesky string ("racecar"), we would only have to compare a sequence with its reverse:

(defn palindrome? [s]
  (= s (reverse s)))
  
(run-tests)

You see, the string gets turned into a sequence of characters when reverse is called on it:

(reverse "racecar")

So to perform a proper comparison we need to call seq on the forward version too.

That's why this is a perfect juxt-ortunity!

Any time we need to produce a vector of items each processed by separate functions, we could be thinking juxt. When this use-case is understood, the function will become a potentially formidable item in our utility-belt. It seems evident to us, as juxt-ers, that encouraging its establishment as an idiomatic Clojure design pattern will lead to code that more clearly demonstrates our intentions. That's what language expressivity is all about, and I believe it's one of Clojure's biggest strengths. And indeed, modeling the problem as a vector of items processed by different functions seems entirely fitting in this case:

(seq "racecar")
(reverse "racecar")

Here we go, time to juxt it up:

((juxt seq reverse) "racecar")

Isn't it beautiful?

From here we can easily compare them with (comp (partial apply =):

(defn palindrome? [s]
  ((comp (partial apply =)
         (juxt seq reverse)) s))
         
(run-tests)

Now that's what I call love at first juxt. See you all tomorrow for more!

Permalink

Exercism - Say

Given a number from 0 to 999,999,999,999, spell out that number in English.

Step 1

Handle the basic case of 0 through 99.

If the input to the program is 22, then the output should be "twenty-two".

Your program should complain loudly if given a number outside the blessed range.

Some good test cases for this program are:

  • 0
  • 14
  • 50
  • 98
  • -1
  • 100

I wanna start by making our base case even simpler and make it just 0 through 9. We'll define a hashmap for the digits:

(def ones
  {0 "zero",
   1 "one",
   2 "two",
   3 "three",
   4 "four",
   5 "five",
   6 "six",
   7 "seven",
   8 "eight",
   9 "nine"})

And extract each key's corresponding value:

(ones 1)

Now for the tens:

(def tens
  {11 "eleven",
   12 "twelve",
   13 "thirteen",
   14 "fourteen",
   15 "fifteen",
   16 "sixteen",
   17 "seventeen",
   18 "eightteen",
   19 "nineteen"})

We can now write a simple function to look it up in the right map:

(defn number [n]
  (if (< n 10)
    (ones n)
    (tens n)))

(number 5)
(number 15)

And then we're gonna need the multiples:

(def multiples
  {2 "twenty"
   3 "thirty"
   4 "forty"
   5 "fifty"
   6 "sixty"
   7 "seventy"
   8 "eighty"
   9 "ninety"})

Here's something that we might need: A function to split a number into its digits:

(defn digits [n]
  (map #(js/parseInt % 10) (str n)))

(digits 56)

That way we can send them off to be processed appropriately. Let's make a function called numcat to do that:

(defn numcat [n]
  (str (multiples (first (digits n)))
       "-" (ones (last (digits n)))))

And wire it up to number:

(defn number [n]
  (cond (< n 10) (ones n)
        (< n 20) (tens n)
        (< n 100) (numcat n)))

(number 45)

Voila! It seems that it works for numbers up to 99 so far! However...

There was another requirement that I feel should be taken quite seriously. Complaining loudly!

(defn number [n]
  (cond (< n 10) (ones n)
        (< n 20) (tens n)
        (< n 100) (numcat n))
        :else "HEY!!! I DON'T KNOW THAT STINKIN' NUMBER!!!")
        
(number 678)

Is that loud enough?

Extension

If you're on a Mac, shell out to Mac OS X's say program to talk out loud. If you're on Linux or Windows, eSpeakNG may be available with the command espeak.

Step 2

Implement breaking a number up into chunks of thousands.

So 1234567890 should yield a list like 1, 234, 567, and 890, while the far simpler 1000 should yield just 1 and 0.

The program must also report any values that are out of range.

Step 3

Now handle inserting the appropriate scale word between those chunks.

So 1234567890 should yield "1 billion 234 million 567 thousand 890"

The program must also report any values that are out of range. It's fine to stop at "trillion".

Step 4

Put it all together to get nothing but plain English.

12345 should give "twelve thousand three hundred forty-five".

The program must also report any values that are out of range.

Extensions

Use and (correctly) when spelling out the number in English:

  • 14 becomes "fourteen".
  • 100 becomes "one hundred".
  • 120 becomes "one hundred and twenty".
  • 1002 becomes "one thousand and two".
  • 1323 becomes "one thousand three hundred and twenty-three".

Source: A variation on JavaRanch CattleDrive, exercise 4a.

(ns say
  (:require [cljs.test :refer-macros [deftest is run-tests]]))

(defn number [num] ;; <- arglist goes here
  ;; your code goes here
)

(deftest zero-test
  (is (= "zero" (say/number 0))))

(deftest one-test
  (is (= "one" (say/number 1))))

(deftest fourteen-test
  (is (= "fourteen" (say/number 14))))

(deftest twenty-test
  (is (= "twenty" (say/number 20))))

(deftest twenty-two-test
  (is (= "twenty-two" (say/number 22))))

(deftest one-hundred-test
  (is (= "one hundred" (say/number 100))))

(deftest one-hundred-twenty-three-test
  (is (= "one hundred twenty-three" (say/number 123))))

(deftest one-thousand-test
  (is (= "one thousand" (say/number 1000))))

(deftest one-thousand-two-hundred-thirty-four-test
  (is (= "one thousand two hundred thirty-four" (say/number 1234))))

(deftest one-million-test
  (is (= "one million" (say/number 1000000))))

(deftest one-million-two-thousand-three-hundred-forty-five-test
  (is (= "one million two thousand three hundred forty-five" (say/number 1002345))))

(deftest one-billion-test
  (is (= "one billion" (say/number 1000000000))))

(deftest a-big-number-test
  (is (= "nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three" (say/number 987654321123))))

(deftest below-zero-is-out-of-range-test
  (is (thrown? IllegalArgumentException (say/number -1))))

(deftest numbers-above-999999999999-out-of-range-test
  (is (thrown? IllegalArgumentException (say/number 1000000000000))))
  
(run-tests)

Permalink

Public technical talks and slides

Over the years, I’ve put together a few public technical talks where the slides are accessible on this site. These are only really nice to view on desktop, and require the use of arrow keys to move around. Long-form notes are also available — generated by a sweet Sphinx and reStructuredText plugin. I figured I’d link to them all here so I don’t lose track:

Using even older slide software called S5, which is also based on reStructuredText, I also have a couple of Python training materials. I’ve given these materials as full-class trainings at various times, including a tutorial at PyCon on web development (the last link here).

Permalink

Parameterizing Datomic Ion Applications

Today's Datomic Cloud release provides an easy way to parameterize ion applications.

Rationale

At runtime, applications need access to configuration data such as the name of a Datomic database. There are several challenges to consider:

  • Configuration values have a lifecycle that is independent of application source code. They should not be hard-coded in the application, and should be managed separately from source code.
  • Applications need a way to obtain their configuration values at runtime.
  • Configuration values may be sensitive, and should not be stored or conveyed as plaintext.
Parameters are a solution to these challenges.

Ion Parameters

Before running your app, you store parameter values under hierarchical keys in AWS Systems Manager Parameter Store. At runtime, your app uses our new APIs to form the keys and read the values. This provides:
  • independent lifecycle for parameter values
  • encryption for sensitive data
  • granular IAM permissions

Get Started

To get started using Datomic's parameter support:

Permalink

Native/Browser SPA versions using ClojureScript and re-frame talk at SCBCN17

Last month I had the pleasure of giving a talk at the Software Craftsmanship Barcelona 2017 conference about what my colleague Francesc and I have been learning lately while working on the mobile and browser versions of a SPA using ClojureScript and re-frame.

I talked mainly about how re-frame's effects and coeffects, re-frame's subscriptions and modelling a UI as FSMs place you in a pit of success, i. e., a design that, according to Jeff Atwood, "makes it easy to do the right things and annoying (but not impossible) to do the wrong things".

It was my first talk in a big conference and I had some technical problems, so I was very nervous at the beginning. After a while I relaxed and felt better. In the end I received more questions than I expected and very nice feedback.

I'd like to thank Modesto for lending me his computer when mine crashed just before the talk and helping me relax.

This is the video of the talk, (thanks Autentia for recording all the talks and for being so kind to me when I was having technical difficulties). I hope you'll find it interesting:



and these are the slides that I've improved after the talk using Modesto's feedback (thanks!!): .

Thanks to Francesc and all the people in Clojure Developers Barcelona Group, Green Power Monitor and Codesai that contributed to improve the talk with their feedback. Also thanks to my colleague Antonio for "persuading" me to give a talk in a conference.

Finally, I'd also like to thank Software Craftsmanship Barcelona 2017 conference organizers for giving me the opportunity to talk at such a great conference and for all the effort they put to make this conference better, edition after edition.

Permalink

Not all watchers are created equal (or how to make yak shaving useful)

I’ve been hacking around with a Clojurescript project recently, and it resulted in a certain amount of yak shaving when I found the watcher system I was using was eating a lot of CPU. On the one hand, yak shaving is bad, because you’re doing other things that aren’t the core task you’d originally meant to do, but there are yaks and there are yaks. In my particular case, I try to make sure my yak shaving results in some improvements to open source projects I’m using and I’d like to encourage you to do the same (which technically makes this the 3rd in my series of “you should be contributing to open source” posts).

Some background first: ‘watchers’ are programs designed to ‘watch’ your source files and do something when they change e.g. run linters/test suites, reload source files in a server, hot-reload into a web browser, etc. They’re ubiquitous in a great many settings, especially for web work, but the linter/test suite case is useful for pretty much everything. There’s versions of them for most languages/frameworks out there, or they might even be built into your existing build tools, and I’d recommend their use for all development work these days.

There’s two core ways to build one: polling or event-based. Polling works by repeatedly checking modified times on files, and is easier to implement and more portable, but can end up being more CPU/IO-intensive especially with the fun trade-off between poll interval v.s. response time, which you want low enough to spot stuff earlier, but high enough to keep the overhead reasonable. Event-based options on the other hand work by asking the operating system to tell you about new changes. This is lightweight and fast, but needs OS-specific support. Most OSes have at least one option for this (epoll/inotify on Linux; ReadDirectoryChangesW on Windows; FSEvents on macOS, etc), but their models of what you can/can’t watch vary and have a tendency to get deprecated/replaced in later versions of an operating system.

I was using lein-auto to make some updates to my project (along with Figwheel which is another watcher in it’s own right), and this was fine until I Dockerised the project. Suddenly something was eating all my CPU even when nothing much was really happening. I eventually managed to narrow down the problem to lein-auto, which was rather surprising, until I read the source code and found out that it was using polling with a default 50ms interval. Apparently on a Mac, the Docker implementation and VM bits with a mounted volume mean that file system operations take a little bit longer than usual and so this was hammering my system.

Ok, let’s rewrite it with a watching implementation. Early work with this still appeared quite slow, and some searching later found me “Is Java 7 WatchService Slow for Anyone Else?” and a 6+ year old JDK bug basically just noting “polling is good enough for Macs, but we should look at this at some point for JDK 9” (for those keeping track, latest is JDK 10). Has anyone done better versions of this? Well, there’s the BarbaryWatchService which is an implementation of a very similar interface to the WatchService, but with proper FSEvents support. Sadly, this had bitrotted rather badly in the three years since it’s last commit, so I went through and fixed all of that, and hopefully the project will wake up at some point.

Of course, that wasn’t directly relevant since I was going to be running this process under Docker, and not directly running on a Mac at all, so I could just use the WatchService directly for my lein-auto changes. However, I’ve now (in the course of writing this) found a library called hawk that abstracts over both WatchService and BarbaryWatchService, although that has it’s own issues I might now have to have a look at as well.

Permalink

The Functional Style — Part 1

Functional programming is a very hot topic nowadays. People are increasingly interested in functional and hybrid-functional languages, such as Haskell, Scala, F#, and Clojure, and functional programming is one of the most popular requested topics for discussion in conferences and programming communities. Since you're reading this, maybe you are interested to find out more about it too; if so, this article series on functional style is meant for you. I have been motivated to write this because I feel that there is a need for more literature explaining how to program in the functional style. I want to illustrate this with helpful code examples and highlight some of the benefits from the functional style.

Functional programming is often discussed in very academic and mathematical terms, but I don't want to go there. That isn't how I learned it myself. I'm not a computer science graduate, and I was never formally taught it. I learned how to program at home, as many 90's adolescents did, and my learning has continued for more than 20 years with professional experience. Moreover, at no time have I ever felt like I knew everything I needed to know about functional programming. I have always been attentive to the current developments in my field and am keenly interested in its history. This series of articles is aimed at similar people — pragmatic programmers who love their field and learn best by writing code, who are humble enough to realize there is always more to learn, and practical enough to see the profit in doing so.

Permalink

Frontend Engineer, Clojurescript

Frontend Engineer, Clojurescript

Workframe | New York, NY

About Workframe

Workframe was founded in 2016 by Andy Parsons, Robert Moore, Matt Smith and Kevin Ryan (Double Click, Gilt, Business Insider, MongoDB, Zola). We're helmed by serial entrepreneurs, growing fast, and leveraging technology to revolutionize the commercial real estate (CRE) industry.

The Workframe team is eclectic, bringing its users a rapidly evolving platform that addresses challenges across the built environment. We are passionate business people, designers and engineers who thrive on delivering value to every CRE professional. Workframe's software as a service (SaaS) product drives efficient, space-centered communication and decision making across project teams and helps them derive insights and efficiency never before possible.

Our software enables tenants, landlords and brokers to navigate the CRE process from site selection to move-in using our innovative project management and visualization core technologies.

About the Role

We are seeking talented frontend software engineers to join us. Engineers on our team play a critical role in developing infrastructure, user-facing features and contributing to our development culture. We are enthusiastic participants in open source, stewarding the Artemis GraphQL client, among other projects. You will:

  • Work closely with the product and design team to get new features out fast
  • Build time-series and schedule visualizations
  • Learn and share functional programming techniques as we hone our tools and approaches
  • Attack hard UX problems
  • Help ensure uptime, performance and user experience are delivered without compromise

Our stack is:

  • Clojure/script
  • Storybook
  • React/Reagent/Re-frame
  • GraphQL
  • Datomic
  • AWS

We are proud to organize and host the Clojure NYC meetup group!

About You

At Workframe, we seek to hire outstanding individuals who embody our DESIGN principles: our people are Diligent, Engaged, Scrappy, Innovative, Genuine and Nurturing. You're a great fit if you enjoy tackling big problems head-on, take your work seriously (but not yourself), do your best when collaborating with others and thrive in a team-oriented environment.

Qualifications and Requirements

  • 2-5 years or more of software engineering experience
  • Exceptional communication and interpersonal skills
  • Love, or at least deep affection for functional programming
  • Ability to think on your feet and express yourself in code
  • Prior startup experience where rapid prototyping is balanced with solid, scalable platform engineering
  • Ability to thrive in a (lowercase) agile environment guided by just-enough process
  • Passion for quality software, techniques and processes to accomplish continuous improvement

Permalink

Copyright © 2009, Planet Clojure. No rights reserved.
Planet Clojure is maintained by Baishamapayan Ghose.
Clojure and the Clojure logo are Copyright © 2008-2009, Rich Hickey.
Theme by Brajeshwar.