I am born in 1973 and live in Tilburg, the Netherlands, with my three gorgeous children.
I am also known as mrhaki, which is simply the initials of his name prepended by mr.
The following Clojure snippet shows how the alias comes together:
(How cool is Clojure that we can express this in a simple code sample ;-) )
I studied Information Systems and Management at the Tilburg University.
After finishing my studies I started to work at a company which specialized in knowledge-based software.
There I started writing my first Java software (yes, an applet!) in 1996.
Over the years my focus switched from applets, to servlets, to Java Enterprise Edition applications, to Spring-based software.
In 2008 I wanted to have fun again when writing software.
The larger projects I was working on were more about writing configuration XML files, tuning performance and less about real development.
So I started to look around and noticed Groovy as a good language to learn about.
I could still use existing Java code, libraries, and my Groovy classes in Java.
The learning curve isn’t steep and to support my learning phase I wrote down interesting Groovy facts in my blog with the title Groovy Goodness.
I post small articles with a lot of code samples to understand how to use Groovy. Since November 2011 I am also a DZone Most Valuable Blogger (MVB); DZone also posts my blog items on their site.
After writing about Groovy I noticed that writing about a subject while learning the subject is very useful.
So it became an habit to start writing small blog posts when I learned something new.
I have spoken at the Gr8Conf Europe and US editions about Groovy, Gradle, Grails and Asciidoctor topics.
Other conferences where I talked are Greach in Madrid, Spain, JavaLand in Germany and JFall in The Netherlands.
I work for a company called JDriven in the Netherlands.
JDriven focuses on technologies that simplify and improve development of enterprise applications.
Employees of JDriven have years of experience with Java and related technologies and are all eager to learn about new technologies.
Introduction
When I started to learn about Clojure I wrote done little code snippets with features of Clojure I found interesting.
To access my notes from different locations I wrote the snippets with a short explanation in a blog: Messages from mrhaki.
I labeled the post as Clojure Goodness, because I thought Clojure is really nice and elegant, and that is how the Clojure Goodness series began.
A while ago I bundled all my blog Groovy Goodness blog posts in a book published at Leanpub.
Leanpub is very easy to use and I could use Markdown to write the content, which I really liked as a developer.
So it felt natural to also bundle the Clojure Goodness blog posts in a book and publish at Leanpub.
In this book the blog posts are bundled and categorized into sections.
Within each section blog posts that cover similar features are grouped.
The book is intended to browse through the subjects.
You should be able to just open the book at a random page and learn more about Clojure
Maybe pick it up once in a while and learn a bit more about known and lesser known features of Clojure
I hope you will enjoy reading the book and it will help you with learning about Clojure, so you can apply all the goodness in your projects.
Core
There Is Truth In Many Things
In Clojure there are only two things false in a boolean or conditional context: false and nil. All other values are threated as true. A value that is false in a boolean context is also called falsey, and a value that is true is called truthy.
In the following example we use false and nil as falsey and several other values as truthy values:
To get the current Clojure version we must use the clojure-version function. The function simply returns the Clojure version we are using from our code.
In the following example we simply check the result of clojure-version and also define a function to get the Javaa version:
In Clojure functions are everywhere. In a previous post we learned that sets can be functions, but Clojure also makes keywords functions. A keyword is a symbol starting with a colon (:) and is mostly used in map entries as key symbol. The keyword as function accepts a map as single argument and returns the value for the key that equals the keyword in the map or nil if the keyword cannot be found.
In the following code we use keywords as function in several examples:
One of the nice things in Clojure is that some data structures are also functions. For me this felt rather strange when learning Clojure (coming from Java), but it can be very powerful. A set in Clojure is also a function. The set as function accept a single argument and it return nil when the argument is not part of the set, otherwise the argument value is returned. This behaviour also makes a set as function a nice predicate to be used for example in collection functions.
In the following example code we use different sets as function:
Clojure supports advanced destructure features. In a previous post we learned about destructuring maps, but we can also destructure vectors, list and sequences in Clojure using positional destructuring. We can define symbols for positions in the sequence to assign the value at a certain position to the symbol. The first symbol in the destructure vector gets the value of the first element in the sequence, the second symbol the value of the second element and so on. To get the remaining elements from the sequence without assigning them to specific symbols we can use & followed by a symbol. Then all remaining elements are assigned as sequence the symbol. Finally we can use :as to get the original vector, list or sequence.
The folowing examples show several destructure definitions for different type of collections and sequences:
When we want to assign key values in a map to symbols we can use Clojure's powerful destructure options. With destructuring a map we can use dense syntax to assign keys to new symbols. For example we can use that in a let special form to assign symbols, but also for function parameters that are a map. When we use it for function parameters we can immediately assign keys to symbols we want to use in the function. Clojure provides a simple syntax to destructure a key value to a symbol using {symbol key} syntax. The value of :key will be assigned to symbol. We can provide default values if a key is not set in the map using :or followed by the symbol and default value. This is very useful if we know not all keys in a map will have values. Finally there is a shorthand syntax to assign keys to symbols with the same name as the key: :keys. We must provide a vector to :keys with the name of the keys, which will automatically assigned to symbols with the same name. To use this destructuring to its fullest the keys in the map must be keywords. We can use the keywordize-keys function in the clojure.walk namespace if we have a map with string keys and we want to transform them to keywords.
In the following example code we see several example of map destructuring:
The Clojure function complement can be used to created a new function that returns the opposite truth value of the old function. The new function accepts the same number of arguments as the old function. Also when we invoke the new function created by the complement the old function is actually invoked and the result is used as argument for the not function to return the opposite truth value. So if the original function returns false or nil the result for the new function is true.
In the following example code we create a new function bad-weather that is the complement of good-weather:
In Clojure we can use the repeat function to get an infinite sequence of a given value. We can pass a length argument to get a fixed size sequence of the value. Clojure also provides the repeatedly function that takes as argument a function without arguments. A infinite sequence of invocations of the function is returned. Just like with the repeat function we can pass a length argument so the returned sequence has a fixed size.
We use the repeat and repeatedly function in the following example:
In Clojure we can use the comp function to create a new function based on multiple other functions. We create a new function by composing other functions. We can invoke the function that is returned from the comp function with input arguments. These arguments are applied to the right most function that was used with comp. Then the output of that function is the input for the next function.
In the following example code we see several usages of the comp function. Also we see how the ordening of the functions can change the output:
Set Default Value For nil Function Argument With fnil
The function fnil can be used to create a new function from an existing function where we define default values for arguments that can be nil. Especially when we want to use a function that we didn't write ourselves this can be helpful to handle nil values in a consistent way. We can prevent for example a NullPointerException by setting a default value. We can define default values for a maximum of three arguments for the original function. When we invoke the function that is returned from the fnil function any extra arguments after the first arguments are simply passed on to the original function.
In the following example code we define a new times function based on the * function. In the example we define a default value for the first three arguments.
Getting Results From Multiple Functions With Juxt Function
The function juxt can be used to get results from multiple functions on the same argument in one go. We pass the functions we want to invoke as arguments to the juxt function. This results in a new function that will return a vector with the results from each original function that is passed to the juxt function. So the first element in the result vector is the result of the first function, the second element is the result of the second function and so on. The documentation of the juxt function shows this clearly as ((juxt a b c)) => [a(x) b(x) c(x)].
In the following example we use the juxt function to apply multiple functions on a string, collection and map:
Pure Function Sample Buying Coffee From FP Programming In Scala Written In Clojure
Some of our colleagues at JDriven work with Scala and we talked about the book Functional Programming in Scala written by Paul Chiusano and Runar Bjarnason. We looked at one of the examples in the first chapter in the book to show the importance of having pure functions without side effects. The example is about buying a cup of coffee and charging a credit card with the purchase. In three examples a function with side effects is refactored to a pure function without side effects. When looking at the example I was wondering how this would look like in Clojure using only functions and simple immutable data structures. We can look at the examples in Scala to see how it is explained and implemented in the book. There are also Kotlin samples available. In this post we see a possible implementation in Clojure to buy coffee and charge our credit card.
The first example is a buy-coffee function with a credit card type as parameter. When we invoke the function with a credit card argument the credit card gets charged as side effect and a coffee type is created and returned. The coffee type is simply a map with a price key.
Let’s write a simple test for the buy-coffee function:
The test runs and shows the function works as expected, but we cannot test the side effect. If the side effect would involve calls to other systems, those systems would be called when we run our tests. That is something we would try to avoid, because it makes testing in isolation more difficult.
In the Scala example the next step is to pass in a Payment type that will take care of charging the credit card. This would make testing the function easier, because we can pass a testable implementation of the Payment type (e.g. a mock). So at least in our tests we can have an implementation that doesn’t access external systems.
For our Clojure example we can pass a payment function as argument to the buy-coffee function. This function takes a credit card type and amount as arguments and will be invoked in the buy-coffee function.
When we write a test we can now check how the payment function is invoked:
But our buy-coffee function is not pure. We have still the side effect, but we made the function better testable. It is also mentioned in Functional Programming in Scala that if we want to invoke our buy-coffee function multiple times, the credit card also gets charged multiple times and this would include extra processing fees as well.
The final implementation of the buy-coffee will no longer charge the credit card, but it will a charge type with all information needed for charging the credit card, together with returning the coffee type. In another function we can handle the actual charging of the credit card by invoking REST calls, database calls or what else is needed. But now it is no longer a concern of our buy-coffee function. Also we can now invoke the buy-coffee function multiple times and combine all returned charge types into a single charge, to save on processing fees.
In our Clojure example we change the buy-coffee function and return both a coffee type and a charge type. The charge type is a map with a key for the credit card and a key for the amount to be charged. Also we introduce the buy-coffees function to show how we can invoke buy-coffee multiple times and combine the charges into a single charge.
And testing the functions is now much easier:
The charge type also makes it easier to work with the charges. For example we can add a coalesce function that takes a collection of charge types and returns all charges per credit card. We can use this information to minimize the processing fees with the credit card company.
And we can write the following test:
In the examples we use a map as type for the coffee, credit card and charge types. We can add records for these types to our Clojure examples to have some more semantics in our code. The good thing is that a records still can be used queries as a map, so a keyword function like :price still works for a Coffee record.
In the next example we add records and use them in the buy-coffee function. Notice the other functions still work without changes.
In our tests we can now also use the functions to create a Coffee, CreditCard and Charge records:
In Clojure we can format a string using Common Lisp format syntax or the Java format string syntax. In the post we will look at the how we can use the Java format string syntax. We must use the format function in the clojure.core namespace. The method delegates to the standard JDK String#format method. The first argument is a format string followed by one or more arguments that are used in the format string. We can look up the syntax of the format string in the Javadoc for the java.util.Formatter class.
In the following example code we use the format function with different format strings:
In the clojure.string namespace we can find several useful function for working with strings. If we want to trim a string we can choose for the trim, trial, trimr and trim-newline functions. To trim all characters before a string we must use the triml function. To remove all space characters after a string we use trimr. To remove space characters both before and after a string we can use the trim function. Finally if we only want to remove the newline and/or return characters we use the trim-newline function.
In the following example we use the different trim functions on strings:
Sometimes we want to see if a string is part of another string. Or if the string value starts or ends with a certain string. In Clojure we can use the includes? function from the clojure.string namespace to check if a string is part of another string value. To see if a string starts with a certain value we can use the starts-with? function from the clojure.string namespace. And to check if a string ends with a given value we use ends-with? from the same namespace.
In the next example code we use these functions and also add a matches? function to check if a string matches with a regular expression defined in a string:
In Clojure we can use the clojure.string/split function to split a string, based on a regular expression, into a vector with string values. Optionally we can also specify a limit on the maximum number of returned string values we want. If we want to split a string based on the newline characters we can use the function clojure.string/split-lines that returns a vector where each element is a line from the original multi-line string.
The following example shows several usages of the split and split-lines functions:
We can use the join function from the clojure.string namespace to join elements from a collection into a string. We can optionally specify a separator that is used to separate each element in the string output. The separator is not used after the last element of the collection. If we don't specify a separator the elements are concatenated without separation. The string representation for each element in the collection is used in the joined end result.
In the following example code we see different usages of the join function:
Replacing Characters In A String With escape Function
The clojure.string namespace contains a lot of useful functions to work with string values. The escape function can be used to replace characters in a string with another character. The function accepts as first argument the string value and the second argument is a map. The map has characters as key that need to be replaced followed by the value it is replaced with. For example the map {\a 1 \b 2} replaces the character a with 1 and the character b with 2.
In the following example code we use the escape function in several cases:
We can search for a value in a string and replace it with another value using the clojure.string/replace function. The first parameter is the original string value that we want to replace parts of. The second parameter can be a string value or regular expression. The last parameter is the replacement value that can be a string value or a function that returns a string value. The function itself gets either a string argument if the match has no nested groups (when match is a regular expression) or a vector with a complete match followed by the nested groups when the match has nested groups.
In the following example we several invocation of the clojure.string/replace function with different arguments:
Merge Maps With Function To Set Value Duplicate Keys
In Clojure we can use the merge function to merge multiple maps into a single map. If a key is in multiple maps the value of the key merged last will be used in the resulting map. If we want to influence how the value of a duplicate key is set we can use merge-with. We specify as first argument the function that will be used when the same key is available in multiple maps. The function must accept two arguments, where the the first argument is the value of the key in the first map and the second argument the value of the same key in the following map. The result is assigned to the key in the resulting map. If we pass more than two maps to the merge-with the function will be called multiple times for a key if it is part of more than two maps.
In the following example we use Clojure core functions and a custom function to merge multiples maps, so we can alter the value for duplicate keys:
To split a collection in Clojure we can use the split-with and split-at functions. The split-with function takes a predicate as first argument and a colletion as second argument. The function will return a vector with two items. The first item is the result of the function take-while with the given predicate. The second item in the result vector is the resul of the drop-while function with the same predicate.
We use the split-at function with a number as first argument followed by a collection to split based on a given number of items. Instead of using a predicate we can define the number of items that we want as the first item in the result vector. The first item in the result vector is the result of invoking the take function. The resulting number of items of the collection will be the second item in the result vector and is achieved by invoking the drop function.
In the following example we use both functions with different arguments:
When we use a function as argument for the map function that returns a collection we would get nested collections. If we want to turn the result into a single collection we can concatenate the elements from the collections by applying the concat function, but we can do this directly with the function mapcat. The function mapcat takes as first argument a function (that returns a collection) and one or more collections as next arguments.
In the following examples we see several uses of mapcat:
If we want to transform items in a collection we can use the map function. If we also want to use the index of the element in the collection in the transformation we must use the map-indexed function. We must provide a function with 2 arguments, where the first argument is the index of the element in the collection and the second argument is the element in the collection.
In the following examples we use the map-indexed function:
Repeat Items In A Collection As Lazy Sequence With cycle
The Clojure function cycle take a collections as argument and creates a lazy sequence by repeating the items in the collection. So if we pass a collection with the characters \a, \b and \c we get a lazy sequence of (\a \b \c \a \b \c ...).
The Clojure function zipmap create a map by interleaving a collection of keys with a collection of values. The first element of the keys collection is the map entry keyword and the first element of the values collection is than the map entry value, and so on for the other elements in the keys and values collections.
In the following example code we use zipmap using different examples of keys and values collections:
In Clojure we can use the range function to create a lazy sequence of numbers. We can optionally specify a start value, end value and define the steps between the numbers. If we use the end value argument that value is exclusive for the returned values in the lazy sequence.
In the following example we invoke the range function with different arguments:
The first function in Clojure returns the first item of a collection. The next function returns a new sequence with all elements after the first element from a collection. Clojure adds some utility methods to combine first and next with different combinations. We can use the function ffirst which is will return the first element of the first element of a collection and the nfirst function to get the next elements from the first element of a collection. We can use the function fnext to get the first element of the next elements of a collection and the function nnext to get the next elements of the next elements of a collection.
In the following example we use the ffirst, nfirst, fnext and nnext:
In Clojure we can use the rand-nth function to get a single random element from a sequence. To get multiple items based on random probability for each item we use the function random-sample. We must set the probability that determines for each item if it is in the result or not.
In the following example code we use rand-nth function:
This next example shows how we can use the random-sample function:
The namespace clojure.set has useful functions when we work with sets. One of the functions is the index function. The index function can be used for a set with map elements to create a new map based on distinct values for one or more keys. The first argument of the function is the set we transform and the second argument is a vector of one or more keys we want to index on. The keys in the new map are maps themselves. The value for each key is a set of maps that have the given keyword/value combination. The new map can be easily queried with the get function to get the values for a key.
In the next example code we see how we can use the clojure.set/index function to first transform a set with map elements to the new map and how to work with the resulting map:
When we are working with sets in Clojure we can use some useful functions from the clojure.set namespace. In a previous post we learned how we can get the difference of several sets. To get the union of several input sets we use the union function of the clojure.set namespace. The function returns a new set that is the union of unique elements from the input sets. A nil value is ignored by the union function.
If we want to get the values from a set that are not part of one or more other sets we must use the difference function in the clojure.set namespace. The function returns a set with all values from the first set that are different from values in other sets.
In the following example we use the difference with several sets:
When we want to get elements from a collection, but not the last element(s), we can use the function butlast and drop-last. The function butlast returns all elements before the last element. If we use the function on an empty collection we get back a nil result. When we use the function drop-last we get back a lazy sequence. Also we can use an extra argument for the function to indicate how many of the last elements we don't want in the result. If we use drop-last on an emtpy collection we get back an empty lazy sequence.
In the following example we use both functions with several collections:
With the function distinct we can remove duplicate elements from a collection. The function returns a lazy sequence when we use a collection argument. Without arguments the function returns a transducer. When we want to remove duplicates and we don't need the lazy sequence result we could also turn a collection into a set with for example the set or into functions.
In the following example we use the distinct function on several collections.
Remove Consecutive Duplicate Elements From Collection
The Clojure core namespace contains many functions. One of the functions is the dedupe function. This function can remove consecutive duplicates from a collection and returns a lazy sequence where only one of the duplicates remain. It will not remove all duplicate elements from the collection, but only when the element is directly followed by a duplicate element. The function returns a transducer when no argument is given.
In the following code sample we use the dedupe function on several collections:
In Clojure we can get part of a vector collection using the subvec function. The function takes a vector as argument, a required begin index and optional end index. The returned value is a vector with part of the values of the original vector starting from the begin up to the end index. If we leave out the optional end index, the size of the vector is used as end index.
In the following example we use the subvec function with and without the end index:
In Clojure we can use the shuffle function with a collection argument to get a new collection where the items of the input collection are re-ordered randomly. The function delegates to the Java java.util.Collections#shuffle method.
In the following example code we use the shuffle method:
To find the maximum or minimum value for numeric values we can use the max and min function. The functions accept one or more numeric arguments and the value that is maximum or minimum is returned. If the numbers are already in a sequence we can use apply max or apply min. If the values are not numbers we can use the max-key or min-key functions. These functions take as first argument a function that returns a number. So we can get the value that has the maximum or minimum return value for the function we pass as first argument.
In the next exmaple code we use the max, min, max-key and min-key functions:
Taking Or Dropping Elements From A Collection Based On Predicate
In Clojure we can take or drop elements from a collection based on a predicate using the functions take-while and drop-while. With the function take-while we take elements as long as the predicate returns true. Once the predicate returns false the function stops returning elements. Using the function drop-while we skip elements in the collection if the predicate returns true. If the predicate returns false the remaining elements in the collection are returned.
In the following example we use take-while and drop-while with different collection types:
Clojure has the partition, partition-all and partition-by functions to transform a collection into a list of sequences with a (fixed) number of items. We can set the number of items in each sequence by providing a number as the first argument of the partition and partition-all functions. Any remainder elements are not in the resulting list of sequences when we use partition, but are when we use partition-all. We can also specify another collection to use values from to fill up the remainder as the third argument of the partition function.\
Optionally we can specify an offset step value as a second argument using both functions. This mean a new partition sequence will start based on stepping through the original collection with the given step value.\
Finally we can use a function to define when a new partition must start with the partition-by function. Every time the function returns a new value a new partition will begin.
In the following example Clojure code we use all three functions with all possible arguments:
If we want to know how often an item is part of a collection we can use the frequencies function. This function returns a map where each entry has the item as key and the number of times it appears in the list as value.
In the following example Clojure code we use the frequencies function:
Reapply Function With Iterate To Create Infinite Sequence
The iterate function create a lazy, infinite sequence based on function calls. The iterate function takes a function and an initial value as arguments. The first element in the sequence is the initial value, next the function is invoked with the previous element as argument and this continues for each new element. Suppose we have a function #(+ 2 %) that adds 2 to the input argument. Then if we use this function with iterate and start with value 1 the first elements of the sequence will be 1, (+ 2 1), (+ 2 3), (+ 2 5). So first element is the initial value, next element is the invocation of the function with input argument 1. The result of this function is 3, which is then the input for the function to calculate the next element and so on.
In the following example code we use iterate in different scenario's:
Checking Predicate For Every Or Any Element In A Collection
In Clojure we can use several functions to see if at least one or all elements in a collection return true or false for a predicate. The function every? only returns true if the predicate function returns true for all elements in the collection. To function not-every? return true if a predicate function return false for all elements in a collection. The some function is a bit different (notice there is no ?) and returns the first logicaltrue value from the predicate function for the elements in the collection. So the return type of the predicate doesn't have to be a Boolean value and then the return type of some is also not a Boolean. If the predicate returns a Boolean value we can use some like a any function (any is not part of Clojure). Clojure provides a not-any? function that returns true if the predicate function returns false for one element in the collection and false otherwise.
The following example uses the different functions on a vector with some cartoon names:
The keep function in Clojure invokes a function on each item in a collection and only returns non-nil results from the function invocation. The result of the keep function is a lazy sequence.
The following example uses the keep function, but also show what results would be when using map function on the same collection with the same function argument:
We can use the flatten function when we have a collection with nested sequential collections as elements and create a new sequence with the elements from all nested collections.
In the following example we use the flatten function:
In the clojure.set namespace we can find the intersection function. This functions accepts one or more sets as arguments and return a new set with all elements that are present in the sets that are passed as arguments to the intersection function. The argument must be a set, so we need to convert other collection or seq values to a set first before we use it as an argument for the function.
In the following example we use one, two or three arguments for the intersection function and also convert other types to a set to be used as argument:
In a previous post we learned how to read text file contents with the slurp function. To write text file content we use the spit function. We content is defined in the second argument of the function. The first argument allows several types that will turn into a Writer object used for writing the content to. For example a string argument is used as URI and if that is not valid as a file name of the file to read. A File instance can be used directly as argument as well. But also Writer, BufferedWriter, OutputStream, URI, URL and Socket. As an option we can specify the encoding used to write the file content using the :encoding keyword. The default encoding is UTF-8 if we don't specify the encoding option. With the option :append we can define if content needs to be appended to an existing file or the content should overwrite existing content in the file.
In the following example we use the spit function with several types for the first argument:
The slurp funtion in Clojure can be used to read the contents of a file and return it as a string value. We can use several types as argument for the function. For example a string argument is used as URI and if that is not valid as a file name of the file to read. A File instance can be used directly as argument as well. But also Reader, BufferedReader, InputStream, URI, URL, Socket, byte[] and char[]. As an option we can specify the encoding used to read the file content using the :encoding keyword. The default encoding is UTF-8 if we don't specify the encoding option.
In the following example we use the slurp function in different use cases. We use a file named README with the content Clojure rocks!:
The Clojure namespace clojure.java.io contains useful functions to work with files. One of those functions is make-parents. We can pass a java.io.File instance as arguments or use the same arguments that can be passed to the file function that is also in this namespace. The function will create all parent directories for the file. The return result is true if the directories are created (they didn't exist before) and false when the directories didn't have to be created (already exist).
In the following example we see an example of usage of the make-parents function:
Working with Java classes from Clojure code is easy. If we want to invoke methods or access fields on instances of Java classes we must first create an instance by invoking the constructor. In Clojure we can do that using the special form new or using a dot (.) notation. The new special form has the class name of the Java class we want to create an instance of as argument followed by arguments for the Java class constructor. With the dot notation we place a . after the class name followed by arguments for the class constructor to create a new instance.
In the following example we see several ways to create an instance of a Java class.
Create And Initialize Object Based On Java Class With doto
It is very easy to work with Java classes in Clojure. If we want to create a new object based on a Java class and invoke methods to initialize the object directly we can use the doto macro. The first argument is an expression to create a new object and the rest of the arguments are functions to invoke methods on the newly created object. The object returned from the first argument is passed as first argument to the method invocations. The doto function returns the object that is created with the first argument.
In the following example code we use the doto function in several cases:
Accessing Java from Clojure is easy. With the dot (.) special form we can invoke for example methods from a Java class or instance. If we want to invoke several methods together where the return value from one method is used to invoke the next method (method chaining) we can use the .. macro. The macro will expand into a nested expression with the . forms.
In the following example we see how to use the .. macro and how we can achieve the same result using nested . expressions and by using the thread first macro:
Sometimes we want to invoke Java methods from our Clojure code. If the Java method accepts a variable arguments (varargs) parameter and we want to invoke the method from Clojure we must pass an array as argument. To create an array in Clojure we can use several functions. The to-array function will transform a collection to an Object[] type. For primitive type arrays we can use for example int-array to get a int[] array. The function into-array is the most flexible function. This function accepts a sequence argument and optionally the class type of the resulting array. Once we have the array we can use it as argument value for the varargs parameter of the Java method we want to invoke.
In the following example we use into-array, to-array and short-array to invoke a Java method with varargs parameter and see how we can build different array types:
The map data structure is used a lot in Clojure. When we want to use Java objects in our Clojure code we can convert the Java object to a map with the bean function. This function will use reflection to get all the properties of the Java object and converts each property with the property value to a key with value in the resulting map. The bean function will not recursively convert nested objects to a map, only the top-level properties are turned into key value pairs.
We see several examples of using the bean function in the following code snippet: