Haskell Data Analysis Cookbook - a Book Review

As with my previous post, Clojure Data Analysis Cookbook - a Book Review, I was this time offered to review Haskell Data Analysis Cookbook by Nishant Shukla.  First impressions: those are two very similar and related books that have some overlapping ideas, but not only are the programming languages used totally different in "genre", the content itself also cover some different data analysis grounds and could be treated as complementary books in that way.


The book itself is very example oriented (much like the Clojure Data Analysis Cookbook), basically being a collection of code recipes for accomplishing various common tasks for data analysis.  It does give you some quick explanations of why and what else to "see also".

It gives you recipes to take in raw data in the form of CSV, JSON, XML, or whatever, including data that lives on web servers (via HTTP GET or POST requests).  Then there are recipes to build up datasets in MongoDB, or SQLite databases.  To recipes to clean up that data, do analysis (e.g. clustering with k-means), to visualizing, presenting, and exporting that analysis.

Each recipe is more or less self-contained, without much in building on top of previous recipes.  It makes the book more "random access".  It's less a book to read through cover to cover, and more of a handy reference to use by full-text searching for key terms, clicking on the relevant topic in the table of contents, or by looking up terms in the index.  It's definitely a book I'd rather have as a PDF ebook so that I can access it anywhere in the world, and so I can do full-text search in.  It does come in Mobi as well as ePub formats, and code samples are provided in a separate zipped download as well.

Having said that, you can tell whether a book was made to be seriously used as a reference or not by looking at its index.  There are 9 pages of indices, equivalent to about 2.9% of the number of pages previous to the index.  This book can certainly be used as a reference.

As a reference book, it's great for people who have already a familiarity with Haskell in general.  If you don't know Haskell, this book won't teach it to you.  That is, unfortunately, possibly a missed marketing opportunity, as those who don't know Haskell (but have knowledge of another programming language) really only needs a small bit to understand enough of how functions are written in Haskell to pick up what's going on in the book.  This means if you know another programming language, know a bit about data analysis, you could use this book to learn some Haskell so long as you pick up the basic syntax with another tutorial in hand (so it's really not a show stopper to using this book).

Similarly, I'd say you had best be familiar with how to do data analysis as a discipline in itself.  If you don't know whether to do clustering or regression, or whether to use a K-NN or K-means, this book won't teach it to you.

Much of that is, of course, echoing the Clojure Data Analysis Cookbook.  Where the Haskell Data Analysis Cookbook differs, makes the two books have a set of complementary ideas.  Whereas both books talk about concurrency and parallelism, the Clojure DAC goes into those topics (including distributed computing) in much more detail.

On the other hand, whereas both books talk about preparing and processing data (prior to performing statistics or machine learning on it), the Haskell DAC goes into much more detail on topics like processing strings with more advanced algorithms (as in computing the Jaro-Winkler distance between strings, not like doing substring/concat operations), computing hashes and using bloom filters, and working with trees and graphs (as in node-and-link graph theory graphs, not grade-school bar graphs).

So in some sense, the Haskell Data Analysis Cookbook has more theory heavy topics (graphs and trees!), whilst the Clojure Data Analysis Cookbook has more "engineering" topics (concurrency, parallelism, and distributed computing).

Neither books are comprehensive treatise on the topic, but someone who needs a practical refresher on working with graphs and trees may find Haskell Data Analysis Cookbook to be quite useful.

All in all, I'd say this is a decent book, because if you have some familiarity of Haskell, have some familiarity with some of the basic technologies like JSON, MongoDB, or SQLite, have taken a class or two of data analysis or machine learning in university (or a MOOC?), and aren't expecting a lot of hand holding from the book, then this book is a great guide to start you off to doing some data analysis with Haskell.

Permalink

Clojure Data Analysis Cookbook - a Book Review

Like yogthos, I was recently asked to review Clojure Data Analysis Cookbook.  With Incanter, data analysis has been one of the "selling points" of Clojure as a practical language.  A practical lisp for practical data analysis.

The book is very example oriented, basically being a collection of code recipes for accomplishing apparently common tasks for data analysis.  It gives you recipes to go from taking raw data in the form of CSV, JSON, or whatever, to making an Incanter dataset, to doing analysis on those datasets (e.g. clustering the data by using a self-organizing map), to saving, viewing, or charting the resultant data.  Each recipe is accompanied by brief explanations, and cross-references to other related recipes in the book.

Each recipe is more or less self-contained, without much in building on top of previous recipes.  It makes the book more "random access".  It's less a book to read through cover to cover, and more of a handy reference to use by full-text searching for key terms, clicking on the relevant topic in the table of contents, or by looking up terms in the index.  It's definitely a book I'd rather have as a PDF ebook so that I can access it anywhere in the world, and so I can do full-text search in.

Having said that, you can tell whether a book was made to be seriously used as a reference or not by looking at its index.  There are 10 pages of indices, equivalent to about 3.2% of the number of pages previous to the index.  This counts as a book to be seriously used as a reference.

As a reference book, it's great for people who have already a familiarity with Clojure (and better yet, Incanter) in general.  If you don't know Clojure, this book won't teach it to you.  If you don't know Incanter, you can pick it up from this book if you're a fast learner (don't expect a lot of hand holding in learning Incanter though).

Similarly, I'd say you had best be familiar with how to do data analysis as a discipline in itself.  If you don't know whether to do clustering or regression, or whether to use a SOM or K-means, this book won't teach it to you.

Also, as a reference book, it is not comprehensive.  For example, as far as neural networks go, it only includes self-organizing maps.  There are no other kinds mentioned.  If you want another kind of neural network, you best know where to look for another Java or Clojure library.

Even with all those caveats, I'd still say this is a pretty decent book.  Why?  Because if you have some familiarity of Clojure, played around with Incanter for a bit to learn that library, have taken a class or two of data analysis in university, and aren't expecting a lot of hand holding from the book, then this book is a great guide to start you off on the road to doing data analysis with Clojure, Incanter, Weka, OpenCL, Cascalog, etc.


Permalink

Full-Stack Developer (Haskell/PureScript) at CollegeVine (Full-time)

Overview

CollegeVine is looking for a product-focused full-stack developer to help engineer the future of mentorship and higher education attainment.

There aren't many industries left that haven't been significantly disrupted by technology in some way, but you're reading about one right here! You will find many opportunities to apply high-leverage computer science (think machine learning, probabilistic reasoning, etc.) as well as plenty of opportunities for the more human side of the problem. As it stands, the current admissions process is a huge source of stress and confusion for students and parents alike. If we execute correctly, your work will impact the entire next generation of college graduates-to-be.

You will join a fast-moving company whose culture centers around authenticity, excellence, and balance. You'll find that everyone likes to keep things simple and transparent. We prefer to be goal-oriented and hands-off as long as you are a self-starter.

Our modern perspective on developer potential means we celebrate and optimize for real output. And that's probably the reason why we're a polyglot functional programming shop, with emphasis on Haskell and functional paradigms. Our infrastructure and non-mission-critical tooling tends to be in whatever works best for the task at hand: sometimes that's Haskell with advanced GHC extensions a-blazin', other times it's minimalist Ruby or bash—basically, it's a team decision based on whatever sits at the intersection of appropriateness, developer joy, quality, and velocity.

As an early-stage company headquartered in Cambridge, MA, we have a strong preference for key members of our team to be located in the Boston metro area; however, given that our company has its roots in remote work (and that it's 2016), we are open to remote arrangements after one year of continuous employment and/or executive approval.

Requirements

You know you are right for this position if:

  • You have at least five years of professional software engineering experience, and at least two years of preference for a high-level programming language that's used in industry, like Haskell, Clojure, OCaml, Erlang, F#, or similar.
  • You have some front-end experience with JS or a functional language that compiles to JS, like PureScript, Elm, Clojurescript, or similar. We use PureScript, React, and ES6 on the front-end. It's pretty awesome.
  • You are a self-starter and internally motivated, with a strong desire to be part of a successful team that shares your high standards.
  • You have great written communication skills and are comfortable with making big decisions over digital presence (e.g. video chat).
  • You have polyglot experience along several axes (dynamic/static, imperative/functional, lazy/strict, weird/not-weird).
  • You are comfortable with modern infrastructure essentials like AWS, Heroku, Docker, CI, etc. You have basic but passable sysadmin skills.
  • You are fluent with git.
  • You instrument before you optimize. You test before you ship. You listen before you conclude. You measure before you cut. Twice.

Benefits

We offer a competitive salary and a full suite of benefits, some of them unconventional, but awesome for the right person:

  • Medical, dental, vision insurance and 401k come standard.
  • Flexible hours with a 4-hour core - plan the rest of your workday as you wish, just give us the majority of your most productive hours. Productivity ideas: avoid traffic, never wait in line at the grocery store, wake up without an alarm clock.
  • Goal-based environment (as opposed to grind-based or decree-based environment; work smarter, not harder; intelligently, not mindlessly). We collaborate on setting goals, but you set your own process for accomplishing those goals. You will be entrusted with a lot of responsibility and you might even experience fulfillment and self-actualization as a result.
  • Daily physical activity/mindfulness break + stipend: invest a non-core hour to make yourself more awesome by using it for yoga, tap-dance lessons, a new bike, massage, a surfboard - use your imagination! Just don’t sit at a computer all day! Come back to work more relaxed and productive and share your joy with the rest of the team. Note: You must present and share proof of your newly enriched life with the team in order to receive the stipend.
  • Equipment/setup budget so you can tool up the way you want. A brand new 15" MBP is standard issue if you have no strong opinions.

Remember: We’re a startup. You’re an early employee. We face challenges. We have to ship. Your ideas matter. You will make a difference.

Get information on how to apply for this position.

Permalink

Clojure Weekly, Aug 26th, 2016

There is always time for a late Friday edition! The Weekly is a collection of bookmarks, normally 4/5, pointing at articles, docs, screencasts, podcasts and anything else that attracts my attention in the clojure-sphere for the last 7 (or so) days. I add a small comment so you can decide if you want to look at the whole thing or not. That’s it, enjoy!

conway.clj Searching for programming perfection is very healthy activity when constrained in a controlled environment (such as spare time and not at work!). This is the very essence of programming katas and less formally any small problem that can be solved multiple times at will. Game of life is one of such small problem that is fun to solve. There’s plenty of game of life in Clojure (I have my very own posted at https://gist.github.com/reborg/09752a1409688365541bda89489d2c6f) and this is one example. I like the predetermined encoding of the neighbours space, the reduce on the tick entry point that can be put in a loop. You probably have yours, feel free to share @reborg.

Design, Composition, and Performance Here’s one from Rich that I never watched. In terms of pure talk performance this is probably one of his best (IMHO): a concise, to the point, coherent exposition (like always, but possibly more this time). I very enjoyed the first part where Rich is teaching how to design, which is essentially about taking things apart on several different dimensions before putting everything back together. The second part is about comparing programming with instrument playing and despite still being an interesting topic, it becomes more about music than anything else. Still from this second part, an interesting take away is that instruments (like programming languages) aren’t designed for the first 5 seconds of beginners experience. Some complexity in Clojure for beginners seems to be related to this aspect. I’d come back to this talk (transcriptions are available) to learn more about good design, especially at the beginning of a project.

(((Bruce Durling))) on Twitter: “Any clojure people going to use spec…” Interesting tweets on specs, design up-front mindset, when to use, how to use them. clojure.spec is definitely pushing the Clojure community to discuss about the benefits of types (as well as the problems related to them). This twitter thread illustrates some of the possibilities: use them all the way down, at the boundaries, for generative testing only, upfront, spec-after and so on. The first question from Bruce is about using them along with Plumatic/Schema. Schema for coercion, core.spec for generative testing.

Category Theory for the Working Hacker Tried hard, but got lost somewhere in the middle :) I suppose that if you can get away without understanding all the details, then the picture you have is exactly as described by Phil: something simple made complicated. I have enough brain to understand that there is something powerful in there, an useful unification of concepts. With category theory, you can work in the abstract for so many things at once: logic, programming, sets, types etc etc.You just need to replace the placeholders and everything is connected back together in your favourite field. Applied category theory is probably more relevant when the types are exposed by the language, so it probably pays off to lear some of it if you are a Haskell programmer. With Lisps, category theory can still make sense, but it’s not a game changer.

Combining Clojure macros: cond-> and as-> Despite the good offering from the standard library, there are entire libraries of extensions to threading macros, because they are so useful and flexible. This post is not a library so you’re free to copy and paste. The example combines cond-> with as-> just in case you need the placement of the threaded expression to appear in different places in a cond-> like thread. The proposed macro is short and easy to read.

jimpil/fudje: Unit testing library for Clojure Never had specific issues with Midje, although nowadays I’m using it mostly for historical reasons (it was the first serious testing framework around, designed around concepts I was used to in OOP). Specifically, this library mentions a couple of problems with Midje: the load of dependencies and the large syntax that Midje brings in. It also mention the need of AOT compiling code with tests but never had that need personally (being tests always outside the uberjar). If those are your problems but you still like the mock-driven TDD this library can be for you.

Permalink

XT16: The Programme

Sometimes you just want to sip a coffee, strum a Ukulele and throw an axe, all while having your mind blown by some of the best software practitioners discussing their most recent technical endeavours, each with the aim of putting the fun and passion back into tech.

This is what the XT16 conference on October 6th is about and the programme has landed.

In order to help us move our minds through a day of deep philosophical insights and creative incitements, we have sourced the best coffee and our very own labelled beer, and also we have a large consignment of Ukuleles being shipped right now that will help us to massage our neurons back into place for further exhilaration.

Our opening and closing keynotes will discuss the humanity of our industry - the ever changing present and future. We have contrarian speakers extolling the values of uber-simplicity versus advanced cross-platform 3D graphical rendering capability.

XT16 is an intimate conference set in a highly secured automated vehicle testing facility in a building that looks a bit like a spaceship. We have the movers and shakers of the London IT scene coming along, ensuring that there will be plenty of intense conversations where you can ponder the meaning of it all.

Tickets are limited and selling out; book yours here.

Lastly we would like to salute our excellent sponsors; pillars of the worldwide Clojure community. These highly successful companies are making a better IT industry for us all.

Permalink

Finite State Machines :: The Clojure Atom 004

Finite State Machines :: The Clojure Atom 004

finite state machines
View this email in your browser


Finite State Machines


Welcome, human state machine, to the fifth issue of The Clojure Atom!

Finite State Machines and Regular Expressions by Eli Bendersky explains one of the best tools (the titular Finite State Machine, or FSM) you can have in your programming toolbox.

Learning about FSMs will have an impact akin to learning about functional programming: After grokking FP, you probably had moments of nerdy pleasure when you realized how easy and simple it is to express data transformations as combinations of map, reduce, filter, and friends. Similarly, once you're comfortable with FSMs, you'll be grateful to have a tool for more simply expressing common programming patterns that you probably bungled in the past.

I've found it particularly useful to model user interface components as state machines. For example, some time ago I was struggling with implementing a typeahead, but once I took the time to list all the possible states and the events that could cause state transitions, it became much easier. When you use modern UI frameworks like re-frame and OM, you model your entire frontend application as a single state machine, and you end up with code that's explicit about state transitions, making it easier to understand how your app works. Next time you're struggling with a project, ask the ol' brain box to spend a few moments considering if it would help to explicitly model whatever you're working on as a state machine.

I hope that inputting this article into your brain results in a state of enjoyment. Have a good weekend!

Daniel

Copyright © 2016 Brave Clojure, All rights reserved.


Want to change how you receive these emails?
You can update your preferences or unsubscribe from this list

Permalink

Senior Tier 2 Support Engineer

Senior Tier 2 Support Engineer

CENX | Ottawa, Ontario, Canada
is a new-generation software company
70000 - 100000

CENX is a new-generation software company -- our vision is to transform the way that operators build and manage their advanced data networking services by fusing big data analytics, deep networking expertise and leading-edge computing technologies. We are a knowledge-based business so our people are our most important asset. We work together in a fast-paced, creative work environment, with colleagues and customers around-the-world. We are looking to expand our team with energetic people that can help make our vision a reality.

Position Summary

Reporting to the Manager, Test Automation and Performance Engineering, the Senior Tier 2 Support Engineer will prime extended investigations of complex field issues, proposing short term workarounds and driving medium and long term fixes at the component at architectural levels.

Finding the root cause of these problems will involve innovation in data gathering and analysis, synthesis of a clear picture following the consultation of several subject matter experts, and reproduction and testing of proposed fixes in a lab setting.

Customer interaction while working troubleshooting sessions and organized customer communication will be necessary to provide timely and well documented updates via email, conference calls and potential site visits.

Key Responsibilities

  • Issue Characterization
  • Take ownership of complex field issues, and discover root cause by working with relevant subject matter experts and/or third party consultants
  • Data Collection
  • Based on analysis of the symptoms, identify key information to guide progress of root cause investigation
  • Develop scripts and tools to gather, analyze and curate data
  • Issue Reproduction
  • Detailed analysis and build out of testing environments to reproduce field issues, validate failure signatures, and work with development to validate fixes
  • Issue Resolution
  • Work with development and architecture to propose, characterize, and drive completion of product improvements

Qualifications

  • An undergraduate degree in computer science, software engineering or a related field
  • A minimum of 7 years experience in a system engineering or customer support role
  • Expert level knowledge of the Linux OS; comfortable gathering and analyzing log files, system configuration, package management, et. cet.
  • Competence in scripting languages such as Python, Perl, or Bash
  • Competence with test tools: Jmeter, SoapUI, Funkload, Robot Framework
  • Thorough understanding of software applications and the interdependencies of hardware and software configuration when investigating issues
  • Demonstrated experience working with application server environments and API's (ex. Tomcat, JBOSS, Websphere & Weblogic)
  • Excellent written communications and an ability to distil the essential facts to summarize complex and difficult problems.
  • Capability to understand and propose solutions to new and complex problems
  • Enthusiastic attitude, eager to continue growing and learning

CENX Canada Inc., is committed to providing accessible employment practices that are in compliance with the Accessibility for Ontarians with Disabilities Act ('AODA'). If you require accommodation due to a disability during any stage of the recruitment process, please do not hesitate to contact us at careers@cenx.com or 613-569-3644.

Permalink

Intermediate or Senior Software Developer

Intermediate or Senior Software Developer

CENX | Ottawa, Ontario, Canada
is a new-generation software company
$61500 - $93000

CENX is a new-generation software company -- our vision is to transform the way that operators build and manage their advanced data networking services by fusing big data analytics, deep networking expertise and leading-edge computing technologies. We are a knowledge-based business so our people are our most important asset. We work together in a fast-paced, creative work environment, with colleagues and customers around-the-world. We are looking to expand our team with energetic people that can help make our vision a reality. www.cenx.com

Position Summary

Reporting to the Manager, Software Development, the Senior Software Developer is responsible for the technical leadership, design and implementation of CENX's Workflow module that provides industry leading service fulfillment and orchestration. In this role, you will be directly involved in the designing and implementing of workflow modules that add value to CENX's state-of-the-art big data, web applications.

Key Responsibilities

  • Providing technical leadership for CENX's Service Fulfillment and Orchestration team using our BPMN based Workflow engine on multiple customer projects and domains.
  • Ensuring that customer projects are delivered successfully to customer expectations, balancing priorities, risks and resourcing.
  • Play a leadership role in evolving the Workflow product line to meet demands of new application domains and value-added services, as well as extending workflow capabilities and value by building on the information model and analytics capabilities provided by CENX.
  • Providing input and technical assessments to influence customer engagements at all stages of the product planning cycle.
  • Working with internal teams to define project delivery phases, balancing customer commitments and resourcing using an Agile approach.

Qualifications

  • An undergraduate degree in computer science, software engineering or a related field.
  • 6-9 years of software development experience.
  • Detailed knowledge of J2EE based development including Spring, Java Persistence / Hibernate, Web Services, HTML, SQL.
  • Proven experience of technical leadership for teams delivering customer facing applications in a dynamic environment while delivering multiple projects simultaneously.
  • Competence in two or more programming languages such as Java, Lisp, Ruby, Scala, Python, Scheme, Clojure, Erlang or C++
  • Object orientated, functional, or concurrent programming experience
  • Proven ability to analyze and document business requirements and corresponding technical solution
  • Proven ability to design and implement complex software requirements specifications
  • Experience with BPMN 2.0, Carrier Ethernet and OSS Software design and implementation an asset.

CENX Canada Inc., is committed to providing accessible employment practices that are in compliance with the Accessibility for Ontarians with Disabilities Act ('AODA'). If you require accommodation due to a disability during any stage of the recruitment process, please do not hesitate to contact us at 613-569-3644.

Permalink

Kata: Variation on Lights Out, flipping behavior on the backend

Lately, in Clojure Developers Barcelona's events, we've been practicing by doing several variations on the Lights Out Kata.

First, we did the kata in ClojureScript using Reagent and Figwheel (described in this previous post).

In the last two meetups (this one and this other one), we redid the kata.

This time instead of doing everything on the client, we used the Compojure library to develop a back end service that reset and flipped the lights, and a simple client that talked to it using cljs-http and core.async libraries.

As we've been doing lately, we did mob programming and REPL-driven development.

First, let's see the code we did for the server:

These are the tests:

and this is the definition of the routes and their handlers using Compojure:

We had some problems with the Same-origin policy until we discovered and learned how to use the Ring middleware for Cross-Origin Resource Sharing.

Finally, this is the code that flips and resets the lights (it's more or less the same code we wrote for the client-only version of the kata we did previously):


Now, let's see the code we wrote for the client:

First, the core namespace where everything is initialized (notice the channel creation on line 12):

Then the lights-view namespace which contains the code to render all the components:

The lights-view's code is also very similar to the one we did for the client-only version of the kata.

And finally the lights namespace which is in charge of talking to the back end and updating the lights atom:

Notice how we used the pipe function to take the values that were coming from the channel returned by the call to cljs-httphttps://github.com/r0man/cljs-http's post function and pass them to the channel from which the code that updates the lights state is taking values.

You can find the code we produced in these two GitHub repositories: the server and the client (see the flip-lights-in-backend branch).

As usual it was a great pleasure to do mob programming and learn with the members of Clojure Developers Barcelona.

Permalink

Focus on spec: Combining Specs with `and`

Clojure's new spec library provides the means to specify the structure of data and functions that take and return data. In this series, we'll take one Clojure spec feature at a time and examine it in more detail than you can find in the spec guide.

In our last post, we explored the simplest specs: predicate functions and sets. In this post we'll look at how you can start to combine specs using the and spec.

For example, we can create a spec that covers the notion of a large even fixed-precision integer with:

(s/valid? (s/and int? even? #(> % 1000)) :foo)  ;; false
(s/valid? (s/and int? even? #(> % 1000)) 10)    ;; false
(s/valid? (s/and int? even? #(> % 1000)) 99999) ;; false
(s/valid? (s/and int? even? #(> % 1000)) 10000) ;; true

For invalid values, spec can also explain to you more precisely why the failure occurred:

(s/explain (s/and int? even? #(> % 1000)) :foo)
;; val: :foo fails predicate: int?
(s/explain (s/and int? even? #(> % 1000)) 10)
;; val: 10 fails predicate: (> % 1000)
(s/explain (s/and int? even? #(> % 1000)) 99999)
;; val: 99999 fails predicate: even?

If we examine a conformed value of this spec, we see that the original value is returned:

(s/conform (s/and int? even? #(> % 1000)) 1111)
;;=> 1111

We will revisit how conformed values flow through s/and specs in a future post as this is not necessarily always the case.

s/and specs also automatically act as a generator that satisfies all the predicates:

(take 5 (s/exercise (s/and int? even? #(> % 1000))))
;;=> ([1814 1814] [1422 1422] [364620 364620] [58602 58602] [4830 4830])

When s/and creates a generator it starts with the first spec (here int?) and generates values:

(take 5 (s/exercise int?))
;;=> ([0 0] [-1 -1] [-2 -2] [1 1] [2 2])

The first spec in an s/and must be able to act as a generator, either due to a built-in mapping or because a custom generator was supplied with it. Most "type" related predicates in Clojure have associated generators and are good choices. Starting an s/and with a predicate like even? would presume too much:

(s/exercise (s/and even? #(> % 1000)))
;; Unable to construct gen at: [] for: even?

Clojure supports many kinds of numbers and even? is a valid question to ask of both fixed and arbitrary precision integers (other predicates like pos? are supported on even more number domains). If even? were to have a generator, what kind of values would it generate? even? shouldn't have to make that decision. It must be combined with another predicate that generates values to produce a valid compound generator.

Values generated from the int? predicate are then passed to the next predicate (even?) and only values that satisfy that predicate are kept:

(take 5 (s/exercise (s/and int? even?)))
;;=> ([0 0] [0 0] [0 0] [-2 -2] [-2 -2])

Finally those values are passed to the final predicate (#(> % 1000)) and only values satisfying that predicate are kept:

(take 5 (s/exercise (s/and int? even? #(> % 1000))))
;;=> ([1620 1620] [1305182 1305182] [3180 3180] [465456 465456] [1198 1198])

In this example the compound generator works because the initial and subsequent domains were relatively "dense" with acceptable values for the next predicate.

Consider this much pickier predicate instead:

(require '[clojure.string :as str])
(s/exercise (s/and string? #(str/includes? % "hi")))
;; Couldn't satisfy such-that predicate after 100 tries.

While the generator would eventually produce a string here or there that includes the substring "hi", the space of acceptable values is much sparser than our prior examples. Fortunately, spec also allows us to supply custom generators using s/with-gen or to override generators by path or name at the point of use when using them in places like clojure.spec.test/instrument and clojure.spec.test/check. Creating custom generators will be the subject of future posts in the series.

To learn more about spec, check out the spec guide or stay tuned for more in this blog series!

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.