PurelyFunctional.tv Newsletter 283: Spec, Error messages!, Games

Issue 283 – July 16, 2018 · Archives · Subscribe

Hi Clojurists,

It used to be, maybe five years ago, that I could keep up with everything in the Clojure community. There were few enough conference talks, blog posts, and libraries that I could feel informed about everything going on. We passed that point a long time ago and it’s feeling more and more difficult to keep up. Every time I talk to someone, there’s something I’ve missed.

In Apropos 12, we talked about the lack of blogs, podcasts, and events around Clojure. So this is a request: please blog, podcast, and host events. There’s plenty of room for more! I love reading The REPL, Daniel Compton’s email newsletter. It covers different stuff from this newsletter, and I enjoy the different perspective. There’s so much room, we’re not competing. We link to eachother’s stuff.

Thank you to everyone who does blog about stuff! I enjoy:

What are your favorite places to learn about Clojure? Like always, just hit reply 🙂

Rock on!
Eric Normand <eric@purelyfunctional.tv>

PS Want to get this in your email? Subscribe!


Clojure Career Workshop ALPHA

There are a handful of tickets left for the Clojure Career Workshop. I want to help you get a job in Clojure. This workshop will support you to improve your resume and find jobs. I’ll also connect you to people I know who can help you on your quest.

This is an ALPHA version, meaning 2 things: you get more attention and it’s cheaper. I haven’t worked out all of the kinks, so to make sure you get what you’re looking for, I’m going to have to give everyone special attention. And because it may be rougly hewn, I’m making it cheaper. But there will only be ten total people in the workshop.

Click the link above to buy tickets and for more information.


Ghostwheel GitHub

One of the cool things about Spec is that it’s a bunch of composable pieces. They’re also optional. Ghostwheel takes advantage of that, providing a powerful library of tools, built on spec. There’s a lot to explore and the documentation looks great.


You should think about some states Podcast

Kevin Lynaugh was on the Future of Coding podcast, talking about everything from state machines to TLA+.


Hyperfiddle

This looks like a cool web framework built on Datomic.


Formally Specifying UIs

Starting from Kevin Lynaugh’s Sketch.systems, Hillel Wayne shows how we can formally specify the links between UI screens so that we can verify interesting properties.


improvements to exception messages and printing Clojure JIRA

Stuart Halloway and Alex Miller are working on improving error messages in Clojure. There’s a much more detailed analysis on the wiki.

Stuart Halloway has been actively discussing error messages on Twitter for the past few weeks. It seems like that discussion is bearing fruit. This is not a reversal on Stuart’s part. In fact, this is a doubling-down on the same principles that make Clojure great but were incompletely applied to error messages.

The changes in the Jira ticket are all about separating (read: decomplecting) the error message (from getMessage()) from its printing. The error messages now are terser so that they can compose better and so that they are reusable. The printer is in charge of displaying relevant information to the user, including the class of the exception.

The default printer, as the Jira ticket now stands, does not print the entire data component of ex-info exceptions. The data component could be a huge nested data structure, and so dominate the printed output. Now the default printer just prints the keys at the top level, which usually fit on one line. They merely give you a first idea about what you will find in the data component when you explore it interactively. All in all, the default error printing seems to be improving, while increasing the freedom and power of the end programmer to customize them.

Though I think error messages can be improved, I know that making good error messages is really hard. If you just focus on error messages, other parts of the system can suffer. I’m glad Stuart has dived into this and found a path forward. And I hope he continues to explain the design choices that make Clojure special.

We talk about this Jira ticket on the latest episode of Apropos.


Nil Punning (or null pointers considered not so bad)

Clojure makes extensive use of nil punning, which means nil can have different meanings in different contexts. I don’t like nil in general (it’s the Billion Dollar Mistake). But the mistake was made in Java and JavaScript, and Clojure needs to live with it. Nil punning is a way for Clojure to make the best of a bad situation.


Making a tale tick

Bryce Covert explains why he chose Clojure to build Tick Tales, his point-and-click adventure game.


Clojure core.async Video course

core.async is a powerful library that makes many kinds of concurrent programming easy. This course teaches the basic concepts of the language and how to apply them to solve problems. core.async changed the game for me, especially in ClojureScript. While core.async has a lot of features, they’re all based on the fundamental concepts of channels and go blocks. This course will help you master them.

The post PurelyFunctional.tv Newsletter 283: Spec, Error messages!, Games appeared first on PurelyFunctional.tv.

Permalink

What does it mean for programs to be built using “whole values”?

John Hughes, FP researcher extraordinaire, says Whole Values is one of the principles of Functional Programming. But what does he mean? We explore this important concept.

Transcript

Eric Normand: One of John Hughes’s principles of functional programming is to use whole values. What does that mean?

Hi, my name is Eric Normand. These are my thoughts on functional programming.

Whole values is a subtle idea. It’s something that I think needs to be shored up and made more definite. He doesn’t ever explain it in definite terms anywhere. He just suggests we use whole values and gives some interesting examples of it.

I would like to try to define it, but I don’t know if I’m ready. I’m just going to explore the idea a little bit and see where it goes. The thing is I do believe that he’s right that this is an important thing in functional programming, it really helps.

I do believe in it. I use it myself, and it really feels right, but that doesn’t mean I could put what I’m doing into words. That’s what I’m trying to do right now.

Let’s imagine that we have some imperative algorithm, and this algorithm requires us to keep track of two different numbers. We make two variables, and we update each as they need to be updated.

For instance, if you wanted to calculate the average of sum of a list of numbers, you could initialize two variables to zero. One of them is called the sum and one of them is called the count. You iterate through the list. Every time you see a number, you add it to the sum, and store it back in sum.

You add one to the count and store it back in count. At the end you divide them out and you have figured out the answer. At each stage of the loop, each iteration through the loop you got these two numbers. You got the sum and the count, but they’re separate. There’s no indication in your program that they go together. They definitely do.

As you know, I’ve talked about calculating an average using the ratio, so that instead of storing the numbers separately, you put them into a tuple where you have a sum and a count in the tuple. That’s an example of keeping the values together and making them whole. Separately they’re not meaningful, but as a whole they are.

This lets you pass it around like an argument. You can have a much more coherent set of operations on them because you have both values all the time.

When I’ve been reading about Smalltalk — again I bring up Smalltalk for some reason — but I think a lot of this stuff was known by the Smalltalk group. The original group in Smalltalk, the whole purpose of objects is to bundle two values together that need to be in a relationship, so that you can transactionally modify them to maintain that relationship.

That’s all we’re talking about is bundling values together into a composite value that those two values are kept in a relationship. It might be three, whatever.

Let’s come up with another example. I was doing some coding yesterday. It was a recursive descent parser. One of the things I needed was two values coming out of a…let’s say I parsed a number out of this stream of characters. I needed two things, the number that I parsed and the rest of the stream like where did I get to when I finished parsing the numbers. I bundled those up as a tuple.

If you extrapolate that to the whole architecture of the entire parser, not just parsing integers but parsing everything, you start to see that this bundling is very useful to be able to say, “Here’s the value that I’ve got and here’s the rest of the stream at all times.”

Then you could be adding to that stream, I mean sorry, adding to that value. Let’s say, you’re parsing a list, you have to parse one item at a time. Add it to the list. You’re maintaining the entire state of the parser in one value, one single value.

Instead of ad hoc, passing these things around as arguments and sometimes you need one and sometimes you need the other, you just always bundle them together. It just makes for a much cleaner interface to everything. I would like to give one more example. This is the example that John Hughes gave.

He was talking about a system that someone came up with to draw graphics. This was quite an old example. The example was that it was a system where an image was represented as a function. The arguments to that function where the axes on which is supposed to draw that picture.

You skew it to fit in the axis. You could have it whether orthogonal, the two axes and wherever the point is where they meet. That’s the bottom left corner. Then, if you were to…sorry, you’re backwards to what I’m seeing. Is you were to skew them like this or move it, it will move the image to another spot and will squish it.

That’s interesting, but really what it’s saying is that that function was complete as a whole value. It could be drawn anywhere on the screen, contained everything it needed to draw. The thing that was variable, where the arguments like, where it’s going to be drawn or what the axes look like.

It was a complete unit. It did nothing. It could be completely opaque because its interface was very clear. It could be composed in very known ways. That’s the example that he gave. I think that’s another interesting example.

This idea of the whole value. Instead of having an image that was a ray of pixels, and then an algorithm, like a function or something else. I guess a function that would take the image and the two axes, make a new image that would skew it. Then take this skewed image. You could then draw that to the screen.

It was done in a much more elegant way that allowed for interesting patterns because you could pass in the axes to a function and it would change the axes, pass them to the image, made it recursively do it so you had this fractal effect.

It’s much more interesting to do cool stuff with. It’s much easier to do that functional recursive stuff when you’re dealing with it at that level.

I don’t know about how beautiful these images were by the way. I do find that that kind of thing helps where you have the whole value. I don’t know about any other examples, but I’m going to try to define it now.

The real essence of it is that you take two or more values, usually it’s a small number of things, and you put them into a composite value. That could be a tuple or you could define a new type.

You put them into this composite value and the composite value represents a semantic whole that you can then define new operations on top of. This is very much like…When I say it like this, it just sounds so much like object-oriented programming where you are grouping state together and putting an interface on it.

That’s not what I see most people doing with object-oriented programming. Usually what they’re doing is…They’re not thinking in terms of the relationships between the data and how to make operations to maintain those relationships.

They’re thinking more like, “What’s all the data we can put in here? Let’s group it together and call it a person or let’s group it together and call it an inventory manager.” I don’t know what they would call it.

Then one of those operations that we need to do on it. We need to read it. We need to write it. We need…They’re not doing this much more relationship based analysis.

Here’s the tip. If you’re doing object-oriented programming, you should look into doing it like this where you’re thinking about…Instead of doing this for-loop and maintaining two different variables, those two variables should be bundled together.

Does it make sense to bundle them together? Once you’ve bundled them together, it could be that the operations…This make it functionally again. The operations on them have interesting properties.

If they’re associative, that means you can do much more free recursion on them. If they are commutative, it means you can distribute your algorithm, not worry about what order things come back in. You’re going to want to bundle those values together anyway.

Maybe if it’s associative, you can find an identity value, you’ve got a monoid. There’s things that you can do with them once they’re bundled together. You can start to analyze the properties of those operations that maintain the relationship.

It’s actually another principle he talks about. He talks about combining forms, it’s what he calls them. Call them operations, but he’s talking about you take two of these whole values and you combine them in some way.

If it’s an average, you’re taking the two averages, you add them up, you have another average. Take two of these images that take the same skewed axes and you can overlay them or you can put them side-by-side or something like that.

It’s a combining form. I’m about to get on the greenway here, a lot of bikes. It’s like a highway for bikes. I’m trying to define this. Trying to define this, this idea of whole values.

Before I define it, I did want to talk a little bit about this talk I saw by Fred George. Fred George is a…I guess he’s a product manager now or project manager, something like that. He’s an old timer, very experienced programmer.

I started getting into him because he talked about what his management style, which is called Developer Anarchy, or something like that. The idea is just give the programmers some KPI, some goals to hit and let them hit it.

Let them go and figure out ways to increase those metrics and don’t give them user stories and stuff like that. Let them come up with them on their own. It required a whole architecture, like a microservices architecture so that they could work independently without breaking the entire system.

He also had another talk called The Secrets of Agile Programming or something like that. Secret Practices of Agile Programming. It was trying to say that when a lot of the agile practices were invented, a lot of them came from extreme programming.

It was assuming that you were programming, basically, like can’t back. Do all these practices, do pair programming. Do continuous deployment. Do test-driven development. All these things that we think of as agile style things modern software development practices.

They also assume that your programming style, your coding style, was in a certain way, so we’ve described the few of these things. One of them, one of the things they said, was your classes should have two or at most three fields.

The audience was like, “What? That’s not possible.” And he’s like, “Go, analyze your classes and the fields that they have. I’ll bet that you’ll see that some of those fields have a stronger relationship to each other than they do to the others.”

If you have a person class, you’ll see that, “Hey, this street name goes together with the zip code much more than it goes together with their salary. Maybe, those should start to be group together to represent that relationship.”

That the whole point of this is to start representing the semantic information in ways that your programming language supports. If you’re just throwing them together like a big bag, you’re not going to be able to move this fast to program as quickly. You just going to have this big bag objects that just do everything.

The secret is to break them out into smaller objects that have much more coherent between the fields. I think that’s very much related to this functional programming idea of whole values. Don’t have a bunch of values that have a relationship and that they’re split apart.

Like they’re split into even something as simple as the two arguments to a function. Put them together. You’ll notice that composite might have certain properties.

There’s also the idea in a whole value that you could have partial solutions to problems. Instead of saying, “Well, we either have the solution or we don’t,” you might have a partial solution.

It’s like this parser example that I gave where you have some value, and then the rest of the problem is being stored or is part of the answer. I parsed four characters for you, here’s the number that that represents, and here’s the rest of the stream.

This is all the characters that were part of that number. You put them together, and it makes sense together.

I’m going long now. I just want to say thanks for listening. It really helps me to get my ideas out, walking and talking, and sharing them with people. I love it that you…

The post What does it mean for programs to be built using “whole values”? appeared first on LispCast.

Permalink

Designing good DSL

DSLs are great tool to reduce complexity and define problems in a compact and succinct way. In case you need to design your own, these are a few common traps to avoid.

Make it verbose

Most well-known example of non-verbose DSL is regular expressions:

([A-Z][a-z]*[,.!?]\s+)*

Even though regular expressions are quite popular, it’s not a good design to copy.

First, most of its syntax beyond the very basics like "X+" or "[^X]" is impossible to remember. It’d be nice to know what "(?<!X)" does without having to look it up first.

Second: how do I google something like that?

And third: it’s really hard to read. There are no clear boundaries, so it’s hard to understand what is part of what. I always struggle even on simple cases like "https?" (it’s either "http" or "https" but it’s really hard to see that at first sight). And when things get complex—and they do get complex quick—you’ll spend more time parsing regex in your head than you would spend writing it anew. I mean, try reading this:

[a-z]{3,10}://([^/?#]*)([^?#]*)(?:\?([^#]*))?(?:#(.*))?

There’s nothing tricky going on, but it’s way too hard to read than it needs to be. That’s why they call Perl write-only language.

Another non-verbose DSL example is Java date and time format string:

"YYYY-MM-DD'T'HH:mm:ss.SSSZ"

More readable (the domain is way simpler) but also less widespread, so you still have to look it up every time. Not a problem while writing, but consider this: you just walking by that code and want to make simple modification (change short month to full month) or even fool-proof that it uses padded 24-hour for hours. Now, is "HH" 24-hour format or 12-hour? Is "MM" the format of month you really want here? Is it even a month, or minutes? It’s all still write-only and ungooglable.

Things get worse if we move to Clojure land. Clojure started as a language that assigned contextual meaning to a few language-defined syntax structures: vector might be a let-binding in let expression, function arguments list in fn and just a data structure. Again, more or less fine in a language because language is the same for all its users, finite and fixed. Learn it once and move along (still, mature developers keep discovering that e.g. case expression treats lists specially etc).

It got worse when library authors treated it as a design guideline. E.g. Datomic rules are specified like this:

[[(descendant? ?p ?c)
  [?p :parent ?c]]
 [(descendant? ?p ?c)
  [?p :parent ?x]
  (descendant? ?x ?c)]]

No words at all, just three-level deep mix of lists and vectors. If you don’t a priori know what’s going on it’s hard to even formulate a question about THAT. Also, as a user, I have to admit it’s really annoying placing all these brackets and parents right every time.

Core.async has the same problem. Here’s how you specify get operation in alt!:

(alt! [c t] ...)

And this is put (value to channel):

(alt! [[c v]] ...)

I mean, this doesn’t correspond to anything in core language or even in core.async itself! It’s just a structure-based syntax for the sake of structure-basedness. Strange that the very same alt! has named options—compare how clearer those are!

(alt! [c t]     ...
      [[c v]]   ...
      :default  nil
      :priority true) 

How to solve? Simple:

Always give alternative options/behaviors/branches long, descriptive names.

E.g. core.match does this right:

(match [x]
  ([1 2] :seq)    ...
  (:or 1 2 3)     ...
  (_ :guard odd?) ...
  :else           ...)

Notice those :seq :or and :guard. Those are the explicit words marking different behaviour, not some implicit shape-defined structure.

Clojure.spec does good job too. It still uses short non-descriptive + and ? (those are borrowed from regexes) but rest is perfectly readable and googlable words: alt, cat, keys, req, coll-of, map-of, every, tuple:

(spec/alt
 :arity-1 ::args+body
 :arity-n (spec/cat
           :bodies (spec/+ (spec/spec ::args+body))
           :attr   (spec/? map?)))

This is how datetime formatting could be done, aided by this principle (example from Tongue):

{hour12}:{minutes-padded}{dayperiod} {month-numeric}/{day}/ {year-2digit}

Verbose, yes, but why would you care about just a few more characters here, when readability is at stake? By making it verbose, even without any prior experience with Tongue, anyone can fool-proof that this code will output something like "1:05PM 7/13/18" and not "13:5PM 07/13/2018". Or even add 0-padding to hours, day and month and maybe even change 12-hour to 24-hour format if needed. Without even looking at the docs! Can you say the same about "H:mm a d/M/y"?

As for regexes, there’re VerbalExpressions:

var tester = VerEx()
    .startOfLine()
    .then('http')
    .maybe('s')
    .then('://')
    .maybe('www.')
    .anythingBut(' ')
    .endOfLine();

Don’t invent second syntax

Sometimes your DSL starts simple and then you figure there’s no way to handle complex cases. So you extend it with advanced ways to do stuff. E.g. Datomic Pull syntax let you simply list attributes you need, attribute = keyword:

[:artist/name :artist/gid ...]

But that way there’s no way to specify additional options: nesting, limits, etc. So even though attributes started as keywords in a list, sometimes they might be specified as a map:

{:artist/tracks [:track/name :track/gid ...]}

Or a list can be used instead of keyword:

(:artist/endYear :default "N/A")

Now even I am confused how to combine default and nesting in a single expression.

Sometimes you start with all-powerful solution and then figure it’s really too much writing for simple cases. So you add shortcuts. E.g. Datomic query let you shorthand this:

(d/q {:find  [?a]
      :where [[?a :artist/name "Beatles"]]})

to this (less brackets):

(d/q [:find  ?a
      :where [?a :artist/name "Beatles"]])

Both ways, now your language has two+ ways of saying the same thing.

Having more than one way to do something is not a virtue, it’s a curse. Your users now have to learn two syntaxes. They need twice as much examples. Answers found on internet might not work because they use different syntax, etc.

My suggestion:

One way to do it + an escape hatch.

You cover most of your users’ needs (that’s the primary value of your DSL anyway) and let users figure the rest in plain old code—best of both worlds.

Don’t be too liberal

Almost the same as the previous one, but on a smaller scale. Sometimes DSLs let you get away with small variations: e.g. in Datomic you can specify default and limit as either keyword, symbol or a string—all are fine (apparently, you can even change order):

(:artist/tracks :limit 10)
(:artist/tracks "limit" 10)
(limit :artist/tracks 10)

Hiccup lets you drop empty attributes map:

[:div {} "Hello, world"]
[:div "Hello, world"]

Core.match lets you drop vector in case you’re matching a single value:

(match [x]
  [:a] ...
  :a   ...) // the same

The thing with special cases, same as with multiple syntaxes, is that you have to learn them, remember about them and recognize them. That’s a problem: it eats up cognitive resources better spent elsewhere.

Also, people in your/other teams will have preferences or would simply not care about consistency. Hence:

The only way to force everybody to always do the same thing is to ban any variations.

Being DSL designer, it’s your responsibility alone.

Keep it small

Rule of thumb:

Your DSL should be entirely memorizable.

That makes using it quick (once you’ve learned it), and this is where the value comes from. If you don’t use it too often or there’s too much syntax, you’ll be required to look at documentation each time before using or reading it. That slows things down, making using DSL an effort and eventually leading to DSL being replaced with a simpler solution.

Don’t try to help too much

Many DSLs were designed to reduce amount of non-DSL code to the absolute zero. They try to help too much. Your stance here should be:

Do in DSL what you know how to do well, leave rest for the users to figure out.

E.g. routing libraries might extract parameters but shouldn’t try to coerce them to other types—it’s really simple to do in your own code. Your users will have full programming language to handle those tricky/rare/exceptional cases.

Sometimes not doing stuff in DSL and leaving specific cases to users leads to less overall complexity.

Conclusion

That’s more or less all I can think of right now. Designing DSLs is a fun and rewarding activity, but as with any design, it’s really hard to get right. I wish you luck on that tricky path, and let me know if it helps.

Permalink

Clojure Don’ts: Thread as

A brief addendum to my last post about Clojure’s threading macros. As I was saying … I said you could use as-> to work around the placement of an argument that doesn’t quite fit into a larger pattern of ->. My example was: (-> results :matches (as-> matches (filter winning-match? matches)) (nth 3) :scores (get…

Read the full article

Permalink

Re-implementing boodle database layer

When I wrote boodle, I didn’t think the database layer thoroughly. The model was simple enough to figure out: one namespace for each table. However, I stuck the queries at the top of these namespaces, using plain strings to compose them.

A working solution, yes, but far from being optimal. Let’s be honest: it’s just plain ugly and prone to error. White spaces, characters to escapes. Not a mess, but neither a smooth ride.

At 7bridges I recently had the chance to play with honeysql. At first I wrongly mistook it for syntactic sugar. A DSL on top of SQL? The horrors of ORM sprang to mind in a rush of anxiety, but I set aside my fears and gave it a chance anyway.

It took me ten minutes to fall in love with honeysql. And turning to boodle for a proper refactoring was the following thought.

A quick example of how prettier queries are now:

(defn select-aims-with-transactions
  []
  (-> (hh/select :a.id [:a.name :aim] :a.target :t.amount)
      (hh/from [:transactions :t])
      (hh/right-join [:aims :a] [:= :a.id :t.id_aim])
      (hh/where [:= :a.achieved false])
      hc/build
      db/query))

No strings, no white spaces, no escaping characters and quoting values. Heaven.

honeysql is also extensible, which makes it simple to add support for operators.

(:require [honeysql.format :as fmt])

;; … other code …

(defmethod fmt/fn-handler "ilike" [_ col qstr]
  (str (fmt/to-sql col) " ilike " (fmt/to-sql qstr)))

During the refactoring process, I noticed something else that needed a better solution: dates.

I was relying on PostgreSQL TO_DATE to format my dates in the queries. honeysql is database-agnostic, so it pushed me to look for a better option.

(:require [java-time :as jt])

;; … other code …

(extend-protocol jdbc/IResultSetReadColumn
  Date
  (result-set-read-column [v _ _]
    (-> v
        jt/local-date
        ud/format-date))

  Timestamp
  (result-set-read-column [v _ _]
    (-> v
        jt/local-date
        ud/format-date)))
        
(extend-protocol jdbc/ISQLValue
  java.time.LocalDateTime
  (sql-value [v] (jt/sql-timestamp v))
  java.time.LocalDate
  (sql-value [v] (jt/sql-timestamp v)))
        
;; … other code …

format-date is just a utility function:

(:require [java-time :as jt])

;; … other code …

(defn format-date
  "Return `date` in dd/MM/yyyy format."
  [date]
  (jt/format "dd/MM/yyyy" date))

If you have any experience with Java, you know dealing with dates and times had not been a piece of cake before Java 8. I briefly mentioned LocalDate when reporting on my experience with Java 8.

Now that I am working with Clojure, dates and times strike back. And thanks to Vadim Platonov, I can safely use Java 8 Date-Time API with clojure.java-time.

Permalink

How is Functional Programming like grocery shopping?

Our understanding of the real world has to be applicable to the software world. Our programming paradigms need to correspond to our intuitions of the real world.

Transcript

Eric Normand: “How is functional programming like grocery shopping?” Hello, my name is Eric Normand. These are my thoughts on functional programming.

I’ve been thinking a lot about this metaphor of grocery shopping. I think it’s a good one because it’s an imperative thing. It’s a thing. It’s an action we take in the world. Yet, functional programming has to apply to it because functional programming is a very practical way of programming.

What’s going on here? Let me explain why I think this is a good example to look at.

If you were to list the steps of what it takes to go shopping for groceries, you might say something like, “I’ll get in the car, I’ll drive to the store, and then I’ll go down the aisles of the store, and I’ll put things I want in my basket. I’ll go to the checkout and I’ll pay for them. I’ll load them in the car. I drive home, and then I put them in the refrigerator.”

That seems pretty reasonable, but if you look closely, a lot of it is left out. In fact, maybe one of the most important things is left out. I’m not talking about all the little sub-steps like how driving to the store requires you to take the key out of your pocket, and put it in the engine and turn it. I’m not talking about that.

I just assumed that those are understood. What I am talking about is something that is just really missing.

If you look at the steps I said, walk through the store, walk through the aisles and put the stuff you want into your shopping cart. Click. I left out. How do you figure out what stuff you want? I didn’t say how we did that.

I really think that that’s one of the keys to why functional programming is successful. It’s it forces you to think of that as an explicit step.

Here’s what I mean. If you look at the three domains — actions, calculations, and data — and analyze this problem that way, the actions are the stuff I listed before. It’s go to the store, put stuff in your shopping cart, stuff like that.

The calculations are like your thinking, your decision making, your planning. You could actually plan your shopping trip. You can plan on what you’re going to buy. It’s something that we often leave out.

Functional programming brings it and gives its full place. I don’t know about you, but when I first started grocery shopping for myself, I would go to the store without even thinking about what I would need. I would get to a section, and be like, “Do I have milk?” I didn’t plan. I didn’t think about what I had and what I needed.

The trip would often…I would buy stuff I didn’t need. I’d forget the stuff that I did need. It was very inefficient.

Functional programming gives a place for that kind of thing. That’s what it is. The calculations, the planning, the decision making, maybe simulating a hypothetical situation like, “What would I choose if I had half a gallon of milk? Would I buy another gallon if I knew I wasn’t going to go back to the store for three weeks?” Things like that.

Those are all just done in your head. They have no effect on the real world. They’re a perfect place for calculations.

That’s what I’ve been thinking about, that calculations are these nice things. They let you think about what you would do without taking any action, without having an effect on the world. You could plan out your trip to the store. You could plan your route through the supermarket. Of course, it gives you a way to think about the data. Your shopping list could be your data.

Of course, there’s all the actions you take while you’re shopping. It’s the driving, the paying, putting stuff in your shopping cart, loading stuff in your car, that kind of thing. Those things are actions.

Let me know what you think about this. This has been rambling. Still, I think it’s useful. I’m going to keep going because this is a pet peeve. I feel a rant coming on.

One of the things that I would like to champion is that functional programming is actually more intuitive than imperative programming. By intuitive, I simply mean it gives places for things. It gives names for things that we deal with in the real world more so than it gives places for things that we deal with in the computer world.

Those examples I’ve given a lot is that in the real world, we want our records to be permanent. We do a lot to archive papers, keep them in filing cabinets, put them in fire-proof boxes, stuff like that. We try to make sure that they’ll last forever.

We enforce disciplines like you can’t change it once you’ve written it. You date it. You put it in the cabinet. All you can do now is read it.

People talk about programming languages like imperative programming being intuitive because you’re taking steps, right? Except then if you can mutate stuff, you’re taking steps but the steps you’re given is like pull this bit of memory into this variable and then modify it again, and then put it over here.

It’s not really intuitive in the sense that you’ve learned this since child’s birth, since you were born. You now understand this thing really well because it’s something you’ve dealt with so many times.

You have object-oriented programming. They talk about it being intuitive, that the classes are the nouns and the methods are the verbs.

First of all, that’s not that intuitive. A lot of people have trouble with that. In school, even in high school — and I went to a very good high school — there were students who couldn’t underline all the verbs in a sentence. This is in high school.

To say, first, that that’s intuitive is just wrong. It’s not as intuitive as the associative property of addition, for instance. That’s something you can learn about the real world by playing with rocks.

I also don’t think that it’s true. [laughs] It’s not intuitive, and it’s not true. If you were to take a description of a problem and turn all the nouns into classes and all the verbs into methods, you would not have a very well-written system. It just would not do the job well. Even if it worked, it wouldn’t be in an intuitive way.

The example I like to give is if you were talking about this grocery shopping experience, you might have broccoli, which is a noun. You give it a verb, buy. What you’re doing is sending a buy message to a broccoli. It’s just not what we do when we go shopping. It has nothing to do with the actual physical shopping experience.

I know that that’s not how real inventory management systems are written. That’s fine, but that is the rhetoric that people use to justify that their language, their OO language is more intuitive. I think it’s wrong. It’s not true. It’s not the way that you would write that system.

Even if you did write it that way, that’s not intuitive in either the sense of knowing nouns and verbs is easy. It’s not intuitive in the sense of that’s actually how the real world works. It doesn’t match our experience. It’s something totally foreign, to send a buy message to a broccoli. We just don’t do that.

Now, I’m not going to sit here and break down what we do do when we shop. I’ll leave that to you as an exercise. That’s actually fun because I think that the object-oriented approach would work well if you did the right analysis. This is not the noun-verb analysis.

There is another argument that object-oriented programming is more intuitive. It has to do with objects, like the world is made of objects that behave in the world. Now, I think that this is true. The world has objects in it, and they behave in the world. You could think of the objects and what their behavior is defined by the class and all the methods in that class.

That is true, but most languages we have do not actually let you define real behavior. Let me put it that way. If you go to small talk where you had objects drawn on a screen, you could simulate, let’s say, an ant colony by making each ant an object.

It would have some kind of clock ticking so that every tick of the clock, it would call this method. That method would move it forward. It would do whatever an ant is supposed to do. You would press run, and it would pull all the ants and start walking around. They would look like a real colony of ants.

That’s very intuitive. The ant is there on the screen. You increase its X and its Y. It moves. It just works really well. That doesn’t help you when you’re actually buying a broccoli. It might help you simulate a shopping experience, simulate what it looks like to observe the whole grocery store where you have an object that’s the buyer.

They walk around the store. They put stuff in their cart, little pictures of stuff, but [laughs] it doesn’t help us keep track of how much money you owe. It doesn’t work. It doesn’t fit. To keep talking about it like it fits is wrong.

The stuff that fits…If you were to actually finish implementing that simulation of a grocery store, you would have to simulate the backend of the store — the inventory management, the purchasing, the printing of the receipts, and the money collection, all that back end stuff, that could then become your backend of a real store.

It’s not going to be the same kind of person class with a buy method. It’s not. I have a whole talk on this. I call them lies in the talk just to have controversial name, an aggressive name to get more views on it.

The talk is called “Lies My OO Teacher Told Me.” It’s nothing against OO. It’s the rhetoric and the way it is taught. It’s a bunch of lies. It’s a bunch of falsehoods that you should put a buy method on a broccoli. Why are you even representing the broccoli as an object in the first place? I don’t think it makes sense.

That’s why I’ve been thinking about groceries, because I think that to explain FP, I need to take some problem that definitely has its imperative counterpart. It’s just a bunch of effects you have on the world.

There’s this other part like, “Why would you separate out the thinking, the planning, the thought process, the decisions? Why would you do that?”

That lets you think about hypotheticals. Isn’t this much more intuitive to think that there’s a place for planning?

Anyway, thanks so much for listening. I really appreciate that you’re there. I really love it when I get messages from people, either agreeing or disagreeing. I get both. I don’t get many neutral messages, I guess that’s normal.

Please, my Twitter is @ericnormand, and my email is eric@lispcast.com. I would love to hear from you. Just send me a message, and we’ll get talking. I love conversations. All right, see you. Bye.

The post How is Functional Programming like grocery shopping? appeared first on LispCast.

Permalink

Clojure from the ground up: functions

We left off last chapter with a question: what are verbs, anyway? When you evaluate (type :mary-poppins), what really happens?

user=> (type :mary-poppins) clojure.lang.Keyword

To understand how type works, we’ll need several new ideas. First, we’ll expand on the notion of symbols as references to other values. Then we’ll learn about functions: Clojure’s verbs. Finally, we’ll use the Var system to explore and change the definitions of those functions.

Let bindings

We know that symbols are names for things, and that when evaluated, Clojure replaces those symbols with their corresponding values. +, for instance, is a symbol which points to the verb #<core$_PLUS_ clojure.core$_PLUS_@12992c>.

user=> + #<core$_PLUS_ clojure.core$_PLUS_@12992c>

When you try to use a symbol which has no defined meaning, Clojure refuses:

user=> cats CompilerException java.lang.RuntimeException: Unable to resolve symbol: cats in this context, compiling:(NO_SOURCE_PATH:0:0)

But we can define a meaning for a symbol within a specific expression, using let.

user=> (let [cats 5] (str "I have " cats " cats.")) "I have 5 cats."

The let expression first takes a vector of bindings: alternating symbols and values that those symbols are bound to, within the remainder of the expression. “Let the symbol cats be 5, and construct a string composed of "I have ", cats, and " cats".

Let bindings apply only within the let expression itself. They also override any existing definitions for symbols at that point in the program. For instance, we can redefine addition to mean subtraction, for the duration of a let:

user=> (let [+ -] (+ 2 3)) -1

But that definition doesn’t apply outside the let:

user=> (+ 2 3) 5

We can also provide multiple bindings. Since Clojure doesn’t care about spacing, alignment, or newlines, I’ll write this on multiple lines for clarity.

user=> (let [person "joseph" num-cats 186] (str person " has " num-cats " cats!")) "joseph has 186 cats!"

When multiple bindings are given, they are evaluated in order. Later bindings can use previous bindings.

user=> (let [cats 3 legs (* 4 cats)] (str legs " legs all together")) "12 legs all together"

So fundamentally, let defines the meaning of symbols within an expression. When Clojure evaluates a let, it replaces all occurrences of those symbols in the rest of the let expression with their corresponding values, then evaluates the rest of the expression.

Functions

We saw in chapter one that Clojure evaluates lists by substituting some other value in their place:

user=> (inc 1) 2

inc takes any number, and is replaced by that number plus one. That sounds an awful lot like a let:

user=> (let [x 1] (+ x 1)) 2

If we bound x to 5 instead of 1, this expression would evaluate to 6. We can think about inc like a let expression, but without particular values provided for the symbols.

(let [x] (+ x 1))

We can’t actually evaluate this program, because there’s no value for x yet. It could be 1, or 4, or 1453. We say that x is unbound, because it has no binding to a particular value. This is the nature of the function: an expression with unbound symbols.

user=> (fn [x] (+ x 1)) #<user$eval293$fn__294 user$eval293$fn__294@663fc37>

Does the name of that function remind you of anything?

user=> inc #<core$inc clojure.core$inc@16bc0b3c>

Almost all verbs in Clojure are functions. Functions represent unrealized computation: expressions which are not yet evaluated, or incomplete. This particular function works just like inc: it’s an expression which has a single unbound symbol, x. When we invoke the function with a particular value, the expressions in the function are evaluated with x bound to that value.

user=> (inc 2) 3 user=> ((fn [x] (+ x 1)) 2) 3

We say that x is this function’s argument, or parameter. When Clojure evaluates (inc 2), we say that inc is called with 2, or that 2 is passed to inc. The result of that function invocation is the function’s return value. We say that (inc 2) returns 3.

Fundamentally, functions describe the relationship between arguments and return values: given 1, return 2. Given 2, return 3, and so on. Let bindings describe a similar relationship, but with a specific set of values for those arguments. let is evaluated immediately, whereas fn is evaluated later, when bindings are provided.

There’s a shorthand for writing functions, too: #(+ % 1) is equivalent to (fn [x] (+ x 1)). % takes the place of the first argument to the function. You’ll sometime see %1, %2, etc. used for the first argument, second argument, and so on.

user=> (let [burrito #(list "beans" % "cheese")] (burrito "carnitas")) ("beans" "carnitas" "cheese")

Since functions exist to defer evaluation, there’s no sense in creating and invoking them in the same expression as we’ve done here. What we want is to give names to our functions, so they can be recombined in different ways.

user=> (let [twice (fn [x] (* 2 x))] (+ (twice 1) (twice 3))) 8

Compare that expression to an equivalent, expanded form:

user=> (+ (* 2 1) (* 2 3))

The name twice is gone, and in its place is the same sort of computation–(* 2 something)–written twice. While we could represent our programs as a single massive expression, it’d be impossible to reason about. Instead, we use functions to compact redundant expressions, by isolating common patterns of computation. Symbols help us re-use those functions (and other values) in more than one place. By giving the symbols meaningful names, we make it easier to reason about the structure of the program as a whole; breaking it up into smaller, understandable parts.

This is core pursuit of software engineering: organizing expressions. Almost every programming language is in search of the right tools to break apart, name, and recombine expressions to solve large problems. In Clojure we’ll see one particular set of tools for composing programs, but the underlying ideas will transfer to many other languages.

Vars

We’ve used let to define a symbol within an expression, but what about the default meanings of +, conj, and type? Are they also let bindings? Is the whole universe one giant let?

Well, not exactly. That’s one way to think about default bindings, but it’s brittle. We’d need to wrap our whole program in a new let expression every time we wanted to change the meaning of a symbol. And moreover, once a let is defined, there’s no way to change it. If we want to redefine symbols for everyone–even code that we didn’t write–we need a new construct: a mutable variable.

user=> (def cats 5) #'user/cats user=> (type #'user/cats) clojure.lang.Var

def defines a type of value we haven’t seen before: a var. Vars, like symbols, are references to other values. When evaluated, a symbol pointing to a var is replaced by the var’s corresponding value:

user=> user/cats 5

def also binds the symbol cats (and its globally qualified equivalent user/cats) to that var.

user=> user/cats 5 user=> cats 5

When we said in chapter one that inc, list, and friends were symbols that pointed to functions, that wasn’t the whole story. The symbol inc points to the var #'inc, which in turn points to the function #<core$inc clojure.core$inc@16bc0b3c>. We can see the intermediate var with resolve:

user=> 'inc inc ; the symbol user=> (resolve 'inc) #'clojure.core/inc ; the var user=> (eval 'inc) #<core$inc clojure.core$inc@16bc0b3c> ; the value

Why two layers of indirection? Because unlike the symbol, we can change the meaning of a Var for everyone, globally, at any time.

user=> (def astronauts []) #'user/astronauts user=> (count astronauts) 0 user=> (def astronauts ["Sally Ride" "Guy Bluford"]) #'user/astronauts user=> (count astronauts) 2

Notice that astronauts had two distinct meanings, depending on when we evaluated it. After the first def, astronauts was an empty vector. After the second def, it had one entry.

If this seems dangerous, you’re a smart cookie. Redefining names in this way changes the meaning of expressions everywhere in a program, without warning. Expressions which relied on the value of a Var could suddenly take on new, possibly incorrect, meanings. It’s a powerful tool for experimenting at the REPL, and for updating a running program, but it can have unexpected consequences. Good Clojurists use def to set up a program initially, and only change those definitions with careful thought.

Totally redefining a Var isn’t the only option. There are safer, controlled ways to change the meaning of a Var within a particular part of a program, which we’ll explore later.

Defining functions

Armed with def, we’re ready to create our own named functions in Clojure.

user=> (def half (fn [number] (/ number 2))) #'user/half user=> (half 6) 3

Creating a function and binding it to a var is so common that it has its own form: defn, short for def fn.

user=> (defn half [number] (/ number 2)) #'user/half

Functions don’t have to take an argument. We’ve seen functions which take zero arguments, like (+).

user=> (defn half [] 1/2) #'user/half user=> (half) 1/2

But if we try to use our earlier form with one argument, Clojure complains that the arity–the number of arguments to the function–is incorrect.

user=> (half 10) ArityException Wrong number of args (1) passed to: user$half clojure.lang.AFn.throwArity (AFn.java:437)

To handle multiple arities, functions have an alternate form. Instead of an argument vector and a body, one provides a series of lists, each of which starts with an argument vector, followed by the body.

user=> (defn half ([] 1/2) ([x] (/ x 2))) user=> (half) 1/2 user=> (half 10) 5

Multiple arguments work just like you expect. Just specify an argument vector of two, or three, or however many arguments the function takes.

user=> (defn add [x y] (+ x y)) #'user/add user=> (add 1 2) 3

Some functions can take any number of arguments. For that, Clojure provides &, which slurps up all remaining arguments as a list:

user=> (defn vargs [x y & more-args] {:x x :y y :more more-args}) #'user/vargs user=> (vargs 1) ArityException Wrong number of args (1) passed to: user$vargs clojure.lang.AFn.throwArity (AFn.java:437) user=> (vargs 1 2) {:x 1, :y 2, :more nil} user=> (vargs 1 2 3 4 5) {:x 1, :y 2, :more (3 4 5)}

Note that x and y are mandatory, though there don’t have to be any remaining arguments.

To keep track of what arguments a function takes, why the function exists, and what it does, we usually include a docstring. Docstrings help fill in the missing context around functions, to explain their assumptions, context, and purpose to the world.

(defn launch "Launches a spacecraft into the given orbit by initiating a controlled on-axis burn. Does not automatically stage, but does vector thrust, if the craft supports it." [craft target-orbit] "OK, we don't know how to control spacecraft yet.")

Docstrings are used to automatically generate documentation for Clojure programs, but you can also access them from the REPL.

user=> (doc launch) ------------------------- user/launch ([craft target-orbit]) Launches a spacecraft into the given orbit by initiating a controlled on-axis burn. Does not automatically stage, but does vector thrust, if the craft supports it. nil

doc tells us the full name of the function, the arguments it accepts, and its docstring. This information comes from the #'launch var’s metadata, and is saved there by defn. We can inspect metadata directly with the meta function:

(meta #'launch) {:arglists ([craft target-orbit]), :ns #<Namespace user>, :name launch, :column 1, :doc "Launches a spacecraft into the given orbit.", :line 1, :file "NO_SOURCE_PATH"}

There’s some other juicy information in there, like the file the function was defined in and which line and column it started at, but that’s not particularly useful since we’re in the REPL, not a file. However, this does hint at a way to answer our motivating question: how does the type function work?

How does type work?

We know that type returns the type of an object:

user=> (type 2) java.lang.long

And that type, like all functions, is a kind of object with its own unique type:

user=> type #<core$type clojure.core$type@39bda9b9> user=> (type type) clojure.core$type

This tells us that type is a particular instance, at memory address 39bda9b9, of the type clojure.core$type. clojure.core is a namespace which defines the fundamentals of the Clojure language, and $type tells us that it’s named type in that namespace. None of this is particularly helpful, though. Maybe we can find out more about the clojure.core$type by asking what its supertypes are:

user=> (supers (type type)) #{clojure.lang.AFunction clojure.lang.IMeta java.util.concurrent.Callable clojure.lang.Fn clojure.lang.AFn java.util.Comparator java.lang.Object clojure.lang.RestFn clojure.lang.IObj java.lang.Runnable java.io.Serializable clojure.lang.IFn}

This is a set of all the types that include type. We say that type is an instance of clojure.lang.AFunction, or that it implements or extends java.util.concurrent.Callable, and so on. Since it’s a member of clojure.lang.IMeta it has metadata, and since it’s a member of clojure.lang.AFn, it’s a function. Just to double check, let’s confirm that type is indeed a function:

user=> (fn? type) true

What about its documentation?

user=> (doc type) ------------------------- clojure.core/type ([x]) Returns the :type metadata of x, or its Class if none nil

Ah, that’s helpful. type can take a single argument, which it calls x. If it has :type metadata, that’s what it returns. Otherwise, it returns the class of x. Let’s take a deeper look at type‘s metadata for more clues.

user=> (meta #'type) {:ns #<Namespace clojure.core>, :name type, :arglists ([x]), :column 1, :added "1.0", :static true, :doc "Returns the :type metadata of x, or its Class if none", :line 3109, :file "clojure/core.clj"}

Look at that! This function was first added to Clojure in version 1.0, and is defined in the file clojure/core.clj, on line 3109. We could go dig up the Clojure source code and read its definition there–or we could ask Clojure to do it for us:

user=> (source type) (defn type "Returns the :type metadata of x, or its Class if none" {:added "1.0" :static true} [x] (or (get (meta x) :type) (class x))) nil

Aha! Here, at last, is how type works. It’s a function which takes a single argument x, and returns either :type from its metadata, or (class x).

We can delve into any function in Clojure using these tools:

user=> (source +) (defn + "Returns the sum of nums. (+) returns 0. Does not auto-promote longs, will throw on overflow. See also: +'" {:inline (nary-inline 'add 'unchecked_add) :inline-arities >1? :added "1.2"} ([] 0) ([x] (cast Number x)) ([x y] (. clojure.lang.Numbers (add x y))) ([x y & more] (reduce1 + (+ x y) more))) nil

Almost every function in a programming language is made up of other, simpler functions. +, for instance, is defined in terms of cast, add, and reduce1. Sometimes functions are defined in terms of themselves. + uses itself twice in this definition; a technique called recursion.

At the bottom, though, are certain fundamental constructs below which you can go no further. Core axioms of the language. Lisp calls these "special forms”. def and let are special forms (well–almost: let is a thin wrapper around let*, which is a special form) in Clojure. These forms are defined by the core implementation of the language, and are not reducible to other Clojure expressions.

user=> (source def) Source not found

Some Lisps are written entirely in terms of a few special forms, but Clojure is much less pure. Many functions bottom out in Java functions and types, or, for CLJS, in terms of Javascript. Any time you see an expression like (. clojure.lang.Numbers (add x y)), there’s Java code underneath. Below Java lies the JVM, which might be written in C or C++, depending on which one you use. And underneath C and C++ lie more libraries, the operating system, assembler, microcode, registers, and ultimately, electrons flowing through silicon.

A well-designed language isolates you from details you don’t need to worry about, like which logic gates or registers to use, and lets you focus on the task at hand. Good languages also need to allow escape hatches for performance or access to dangerous functionality, as we saw with Vars. You can write entire programs entirely in terms of Clojure, but sometimes, for performance or to use tools from other languages, you’ll rely on Java. The Clojure code is easy to explore with doc and source, but Java can be more opaque–I usually rely on the java source files and online documentation.

Review

We’ve seen how let associates names with values in a particular expression, and how Vars allow for mutable bindings which apply universally. and whose definitions can change over time. We learned that Clojure verbs are functions, which express the general shape of an expression but with certain values unbound. Invoking a function binds those variables to specific values, allowing evaluation of the function to proceed.

Functions decompose programs into simpler pieces, expressed in terms of one another. Short, meaningful names help us understand what those functions (and other values) mean.

Finally, we learned how to introspect Clojure functions with doc and source, and saw the definition of some basic Clojure functions. The Clojure cheatsheet gives a comprehensive list of the core functions in the language, and is a great starting point when you have to solve a problem but don’t know what functions to use.

We’ll see a broad swath of those functions in Chapter 4: Sequences.

My thanks to Zach Tellman, Kelly Sommers, and Michael R Bernstein for reviewing drafts of this chapter.

Permalink

Datomic Cloud Monitoring and Ion Cast

The new datomic.ion.cast library lets your application produce monitoring data that are integrated with Datomic's support for AWS CloudWatch.

Datomic Cloud and AWS CloudWatch

AWS CloudWatch provides a powerful set of tools for monitoring a software system running on AWS:
  • Collect and track CloudWatch Metrics -- variables that measure the behavior of your system.
  • Configure CloudWatch Alarms to notify operations or take other automated steps when potential problems arise.
  • Monitor, store, and search CloudWatch Logs across all your AWS resources.
  • Create CloudWatch Dashboards that provide a single overview for monitoring your systems.
Datomic Cloud is fully integrated with all of these AWS monitoring tools. On the producing side, Datomic creates metrics and logs; and on the consuming side, Datomic organizes metrics in custom dashboards like this Production Dashboard:

Production Dashboard

datomic.ion.cast

With the introduction of Datomic Ions, your entire application can run on Datomic Cloud nodes. The datomic.ion.cast namespace lets Ion application code add your own monitoring data alongside the monitoring data already being produced by Datomic.  Cast supports four categories of monitoring data:
  1. An event is an ordinary occurence that is of interest to an operator, such as start and stop events for a process or activity.
  2. An alert is an extraordinary occurrence that requires operator intervention, such as the failure of some important process.
  3. Dev is information of interest only to developers, e.g. fine-grained logging to troubleshoot a problem during development. Dev data can be much higher volume than events or alerts.
  4. A metric is a numeric value in a named time series, such as the latency for an operation.
To get started using ion.cast, you can

Permalink

Library focus

Software projects rely on libraries heavily. Usually it’s pretty simple: you have a need, you pick a library, you integrate it and get results. Most of the time it’s advantegeous—economically—because it’s faster than rolling your own implementation.

Clojure, though, faces an unique challenge here: many problems that have been addressed by libraries can be trivially solved in your own code too, and it can be done in a time that is comparable to the time that’ll take you to figure out a library. I’m not exaggerating—it’s really that simple.

Sure, there are libraries that do heavy lifting—stuff like DataScript or Instaparse, those will take you more than a day to write. But a good half of all libraries, or even more, can be reproduced in day’s time. Maybe not for all use cases, but for all your cases at least. If you think of it, all clojure.test does is just asserting for you, Component runs functions that you give it to run, compojure/bidi/other routers do pretty basic regexp matching on strings, etc.

So, if you can solve your problems by writing your own code, and there’re no economic reasons not to, why shouldn’t you? You’ll get more freedom and better fit for your unique problems, right?

Well, you shouldn’t do it because you’re badly positioned to do so. Libraries and products need different focus. If you’re writing a production project, there’re no powers in play that’ll stop you from compromising greater but further good to the immediate needs. You’ll inevitably end up with incoherent, incomplete home-grown “library” that’s pain to use (as the rest of your code is) and is tightly coupled to your project.

Code is probably the simplest to isolate, but the assumptions, the features you decided to focus on will create the unfortunate coupling and compromised vision. Sometimes you’ll skip on crucial parts because there’s no time, sometimes you’ll focus on parts that shouldn’t be solved in there (but were very convenient—and quick—to solve there nevertheless). And of course you’ll never add stuff in advance, so it’ll never be finished, not really, and will change all the time.

So no, you can’t build a project and publish parts of it open-source while at it, not in a valuable way. It’s either one or the other.

I’m only writing about this because the difference’s so subtle it’s almost magical: the very same people, perfectly capable software engineers, when put in a bigger project context, almost physically can’t produce anything comparable to a library code in terms of clarity, isolation and reusability.

So yeah, choosing a library over rolling your own implementation has a benefit: a benefit of author’s focus that’s different from your immediate needs.

And no, don’t plan a project’s architecture on a library you plan to write first that’ll make rest of the development easier. That’ll never fly.

Permalink

Daily Coding Puzzles

I think a lot of people know this at this point, but I love writing code. To wake myself up in the morning and get my brain running, I normally solve a code puzzle first thing when I get to work.

I normally find these on Project Euler, CodeWars, or HackerRank -- though I'm totally open to suggestions if anybody has a really good alternate resource! I really love the problem-solving nature of these code challenges, and how I can sometimes can come up with really cool out of the box solutions to them. I do feel like they help me become a stronger programmer, and an added bonus is that if I am interviewing at the time a lot of interview questions are similar to these (for better or for worse).

Since I'm already doing these every day, I thought it would be really cool to share my results on social media to keep me accountable and to see how other people solve the same problem. I normally solve these challenges in Python or JavaScript, but other people have been posting in Ruby, Rust, Ramda, and Clojure so far (which is so cool to see!). Some of them I have solved before at some point, so I post multiple answers in different languages or my refactors!

If you would like to follow along and post your own solutions (or just see other people's), follow me on Twitter or I've been using the hashtag #CodingPuzzle on them, so you could follow there instead! I normally post in between 8 and 9 AM EST since that is normally when I get to work! It's also led to some interesting discussions on efficiency and the strengths of different programming languages for solving these types of problems! These problems are also a variety of difficulties, so if one day's problem is too hard, still follow the next day for a new one!

To get started, today's problem was Project Euler Problem 2: Even Fibonacci Numbers: Each new term in the Fibonacci sequence is generated by adding the previous two terms. Find the sum of the even-valued terms. Please post your answer here!

If you want to catch up on the previous ones, they were:

Hope to see your answers!

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.