Functional Programming Patterns in Scala and Clojure 1st Edition Michael Bevilacqua-Linn instant download
Functional Programming Patterns in Scala and Clojure 1st Edition Michael Bevilacqua-Linn instant download
https://ebookgate.com/product/functional-programming-patterns-in-
scala-and-clojure-1st-edition-michael-bevilacqua-linn/
https://ebookgate.com/product/programming-scala-2nd-edition-
scalability-functional-programming-objects-second-edition-dean-
wampler/
ebookgate.com
https://ebookgate.com/product/learning-scala-practical-functional-
programming-for-the-jvm-1st-edition-jason-swartz/
ebookgate.com
https://ebookgate.com/product/programming-clojure-1st-edition-stuart-
halloway/
ebookgate.com
https://ebookgate.com/product/clojure-programming-1st-edition-chas-
emerick/
ebookgate.com
Programming in Scala 2nd 2nd Edition Martin Odersky
https://ebookgate.com/product/programming-in-scala-2nd-2nd-edition-
martin-odersky/
ebookgate.com
https://ebookgate.com/product/scala-high-performance-programming-1st-
edition-theron/
ebookgate.com
https://ebookgate.com/product/the-joy-of-clojure-thinking-the-clojure-
way-1st-edition-michael-fogus/
ebookgate.com
https://ebookgate.com/product/science-learning-and-instruction-1st-
edition-linn/
ebookgate.com
This book is an absolute gem and should be required reading for anybody looking
to transition from OO to FP. It is an extremely well-built safety rope for those
crossing the bridge between two very different worlds. Consider this mandatory
reading.
➤ Colin Yates, technical team leader at QFI Consulting, LLP
This book sticks to the meat and potatoes of what functional programming can do
for the object-oriented JVM programmer. The functional patterns are sectioned in
the back of the book separate from the functional replacements of the object-oriented
patterns, making the book handy reference material. As a Scala programmer, I even
picked up some new tricks along the read.
➤ Justin James, developer with Full Stack Apps
This book is good for those who have dabbled a bit in Clojure or Scala but are not
really comfortable with it; the ideal audience is seasoned OO programmers looking
to adopt a functional style, as it gives those programmers a guide for transitioning
away from the patterns they are comfortable with.
➤ Rod Hilton, Java developer and PhD candidate at the University of Colorado
Michael Bevilacqua-Linn
Preface . . . . . . . . . . . . . . ix
Bibliography . . . . . . . . . . . . 231
Index . . . . . . . . . . . . . . 233
This book would have suffered greatly without a great group of technical
reviewers. My thanks to Rod Hilton, Michajlo “Mishu” Matijkiw, Venkat Sub-
ramaniam, Justin James, Dave Cleaver, Ted Neward, Neal Ford, Richard
Minerich, Dustin Campbell, Dave Copeland, Josh Carter, Fred Daoud, and
Chris Smith.
Finally, I’d like to thank Dave Thomas and Andy Hunt. Their book, The
Pragmatic Programmer, is one of the first books I read when I started my
career. It made a tremendous impact, and I’ve still got my original dog-eared,
fingerprint-covered, bruised and battered copy. In the Pragmatic Bookshelf,
they’ve created a publisher that’s truly dedicated to producing high-quality
technical books and supporting the authors who write them.
Used together, these patterns let programmers solve problems faster and in
a more concise, declarative style than with object-oriented programming alone.
If you’re using Java and want to see how functional programming can help
you work more efficiently, or if you’ve started using Scala and Clojure and
can’t quite wrap your head around functional problem-solving, this is the
book for you.
Before we dig in, I’d like to start off with a story. This story is true, though
some names have been changed to protect the not-so-innocent.
A Tale of Functional Programming
by: Michael Bevilacqua-Linn, software firefighter
The site isn’t down, but an awful lot of alarms are going off. We trace the problems to changes
someone made to a third-party API we use. The changes are causing major data problems on
our side; namely, we don’t know what the changes are and we can’t find anyone who can tell
us. It also turns out the system that talks to the API uses legacy code, and the only guy who
knows how to work on it happens to be away on vacation. This a big system: 500,000-lines-of-
Java-and-OSGI big.
Support calls are flooding in, lots of them. Expensive support calls from frustrated customers.
We need to fix the problem quickly. I start up a Clojure REPL and use it to poke around the
problem API.
My boss pokes his head into my office. “How’s it going?” he asks. “Working on it,” I say. Ten
minutes later, my grandboss pokes his head into my office. “How’s it going?” he asks. “Working
on it,” I say. Another ten minutes pass by when my great-grandboss pokes his head into my
office. “How’s it going?” he asks. “Working on it,” I say. I get a half hour of silence before the CTO
pokes his head into my office. “Working on it,” I say before he opens his mouth.
An hour passes, and I figure out what’s changed. I whip up a way to keep the data clean until
the legacy developer gets back and can put together a proper fix. I hand my little program off
to the operations team, which gets it up and running in a JVM, somewhere safe. The support
calls stop coming in, and everyone relaxes a bit.
A week or so later at an all-hands meeting, the great-grandboss thanks me for the Java program
I wrote that saved the day. I smile and say, “That wasn’t Java.”
Two of the patterns that we’ll see in this book, Pattern 21, Domain-Specific
Language, on page 218, and Pattern 15, Chain of Operations, on page 159,
contributed greatly to this story’s happy ending.
The TinyWeb extended example serves a few purposes. It will let us see how
several of the patterns we cover in this book fit together in a comprehensive
manner. We also use it to introduce the basics of Scala and Clojure. Finally,
since we’ll transform TinyWeb from Java to Scala and Clojure bit by bit, it
gives us a chance to explore how to easily integrate Java code with Scala and
Clojure.
The remainder of the book is organized into two sections. The first, Chapter
3, Replacing Object-Oriented Patterns, on page 39, describes functional
replacements for object-oriented patterns. These take weighty object-oriented
patterns and replace them with concise functional solutions.
Peter Norvig, author of the classic Lisp text Paradigms of Artificial Intelligence
Programming: Case Studies in Common Lisp [Nor92], current director of
research at Google, and all-around very smart guy, pointed out in Design
Patterns in Dynamic Languages that expressive languages like Lisp could turn
classic object-oriented patterns invisible.1
Pattern Template
The patterns are laid out using the following format, with some exceptions.
For example, a pattern that doesn’t have any other common name would not
have the Also Known As subsection, and the Functional Replacement subsec-
tions only apply to the patterns in Chapter 3, Replacing Object-Oriented Pat-
terns, on page 39.
Intent
The Intent subsection provides a quick explanation of the intent of this pattern
and the problem it solves.
Overview
Here is where you’ll find a deeper motivation for the pattern and an explanation
of how it works.
Also Known As
This subsection lists other common names for the pattern.
1. http://norvig.com/design-patterns/
Functional Replacement
Here you’ll find how to replace this pattern with functional programming
techniques—sometimes object-oriented patterns can be replaced with basic
functional language features and sometimes with simpler patterns.
Example Code
This subsection contains samples of the pattern—for object-oriented patterns,
we first show a sketch of the object-oriented solution using either class dia-
grams or a sketch of the Java code before showing how to replace them in
Clojure and Scala. Functional patterns will be shown in Clojure and Scala
only.
Discussion
This area provides a summary and discussion of interesting points about the
pattern.
Related Patterns
This provides a list of other patterns in this book that are related to the current
one.
Both Scala and Clojure run on a Java virtual machine (JVM), so they interop-
erate well with existing Java libraries and have no issues being dropped into
the JVM infrastructure. This makes them ideal to run alongside existing Java
codebases. Finally, while both Scala and Clojure have functional features,
they’re quite different from each other. Learning to use both of them exposes
us to a very broad range of functional programming paradigms.
Clojure is a modern take on Lisp. It has Lisp’s powerful macro system and
dynamic typing, but Clojure has added some new features not seen in older
Lisps. Most important is its unique way of dealing with state change by using
reference types, a software transactional memory system, and efficient
immutable data structures.
As we introduce the patterns, we’ll explore both of these languages and their
features, so this book serves as a good introduction to both Scala and Clojure.
For further detail on either language, my favorite books are Programming
Clojure [Hal09] and The Joy of Clojure [FH11] for Clojure, and Programming
Scala: Tackle Multi-Core Complexity on the Java Virtual Machine [Sub09] and
Scala In Depth [Sue12] for Scala.
From there you can jump around, pattern by pattern, as needed. The patterns
covered earlier in Chapter 3, Replacing Object-Oriented Patterns, on page 39,
and Chapter 4, Functional Patterns, on page 137, tend to be more basic than
later ones, so they’re worth reading first if you have no previous functional
experience.
A quick summary of each pattern can be found in Section 1.2, Pattern Glos-
sary, on page 4, for easy browsing. Once you’re through the introduction,
you can use it to look up a pattern that solves the particular problem you
need to solve.
Online Resources
As you work through the book, you can download all the included code files
from http://pragprog.com/titles/mbfpp/source_code. On the book’s home page at
http://pragprog.com/book/mbfpp, you can find links to the book forum and to report
errata. Also, for ebook buyers, clicking on the box above the code extracts
downloads the code for that extract for you.
Second, the functional world also has its own set of useful patterns. These
patterns focus on writing code that avoids mutability and favors a declarative
style, which helps us write simpler, more maintainable code. The two main
sections of this book cover these two sets of patterns.
You may be surprised to see the first set. Don’t the patterns we know and
love extend across languages? Aren’t they supposed to provide common
solutions to common problems regardless of what language you are using?
The answer to both questions is yes, so long as the language you are using
looks something like Java or its ancestor, C++.
That’s not to say that foreach loops are exactly equivalent to the Iterator. A
foreach won’t replace an Iterator in all cases. The problems they do address
are solved in a simpler way. Developers prefer the built-in foreach loops for the
common-sense reasons that they are less work to implement and are less
error prone.
Adding functional features and techniques adds more tools to our program-
ming toolbox, just as Java 1.5 did with its foreach loop but on a grander scale.
These tools often complement the tools we already know and love from the
object-oriented world.
The second set of patterns we cover in this book, native functional patterns,
describes the patterns that evolved out of the functional style. These functional
patterns differ from the object-oriented patterns you may be familiar with in
a few key ways. The first, and most obvious, is that functions are the primary
unit of composition, just as objects are in the object-oriented world.
Another key difference lies in the patterns’ granularity. The patterns from
Design Patterns: Elements of Reusable Object-Oriented Software [GHJV95] (one
of the original drivers of the software patterns movement) are generally tem-
plates that define a few classes and specify how they fit together. Most of
them are medium size. They often don’t concern themselves either with very
small issues that encompass just a few lines of code or with very large issues
that encompass entire programs.
The functional patterns in this book cover a much broader range, as some of
them can be implemented in a line or two of code. Others tackle very big
problems, such as creating new, miniature programming languages.
The range is in line with the book that started the patterns movement in
general, A Pattern Language [AIS77]. This book on architectural patterns
starts off with the very big “1—Independent Regions” pattern, which outlines
why the planet should be organized into political entities of about 10,000
people, and goes all the way down to “248—Soft Tile and Brick,” which explains
how to make your own bricks.
Before we dig into the various patterns in this book, let’s spend some time
getting familiar with functional programming itself.
Favor pure functions: Pure functions are functions that have no side effects.
A side effect is an action that the function does that modifies state outside
the function.
However, other problems are hard, if not impossible, to solve using strict
functional programming techniques. A compiler is a pure function. If you put
a program in, you expect to get the same machine code out every time. If you
don’t, it’s probably a compiler bug. Google’s search engine, however, is not a
pure function. If we got the same results from a Google search query every
time, we’d be stuck with a late 1990s view of the Web, which would be quite
tragic.
Scala has more support for mutable data, but immutable data is preferred.
For instance, Scala has both mutable and immutable versions of its collections
library, but the immutable data structures are imported and used by default.
This section introduces two basic types of functional features. The first type,
higher-order functions, allows us to pass functions around as first-class data.
The second, anonymous functions, allows us to write quick one-off functions
without giving them a name. These features combine to let us replace most
instances of Functional Interface very concisely.
Let’s focus on a few goals for this example. The first is to see several patterns
working together in one codebase before we go into them in more detail.
The second is to introduce basic Scala and Clojure concepts for those unfa-
miliar with either, or both, of the languages. A full introduction to the lan-
guages is beyond the scope of this book, but this section gives you enough
of the basics to understand the majority of the remaining code.
Finally, we’ll work existing Java code into a Scala or Clojure codebase. We’ll
do this by taking the Java version of TinyWeb and transforming it into Scala
and Clojure piece by piece.
Template Method, on page 83. Views are implemented using the Strategy
pattern, covered in Pattern 7, Replacing Strategy, on page 92.
Our framework is built around core pieces of data objects, HttpRequest and
HttpResponse. We want these to be immutable and easy to work with, so we are
going to build them using the Builder pattern discussed in Pattern 4,
Replacing Builder for Immutable Object, on page 62. Builder is a standard way
of getting immutable objects in Java.
Finally, we’ve got request filters that run before a request is handled and that
do some work on the request, such as modifying it. We will implement these
filters using the Filter class, a simple example of Pattern 1, Replacing Functional
Interface, on page 40. Our filters also show how to handle changing data using
immutable objects.
We’ll start off with a look at our core data types, HttpRequest and HttpResponse.
JavaExamples/src/main/java/com/mblinn/oo/tinyweb/HttpResponse.java
package com.mblinn.oo.tinyweb;
This approach encapsulates all mutability inside of a Builder object, which then
builds an immutable HttpResponse. While this gives us a clean way of working
with immutable data, it’s quite verbose. For example, we could create a simple
test request using this code:
Without using Builder we’d need to pass all of our arguments in the construc-
tor. This is okay for our small example, but this practice grows unwieldy when
working with larger classes. Another option would be to use a Java Bean–style
class with getters and setters, but that would require mutability.
Let’s move on and take a quick look at HttpRequest. Since the class is similar
to HttpResponse (though it lets us set a request body, headers, and a path), we
won’t repeat the code in full. One feature is worth mentioning, though.
return builder;
}
This may seem wasteful, but the JVM is a miracle of modern software engi-
neering. It’s able to garbage-collect short-lived objects very efficiently, so this
style of programming performs admirably well in most domains.
First we’ll need a View interface, which has a single method, render(). render()
takes in a model in the form of a Map<String, List<String>>, which represents the
A large class of software bugs boil down to one section of code modifying data in
another section in an unexpected way. This type of bug becomes even more heinous
in the multicore world we all live in now. By making our data immutable, we can
avoid this class of bugs altogether.
Using immutable data is an oft-repeated bit of advice in the Java world; it’s mentioned
in Effective Java [Blo08]—Item 15: Minimize Mutability, among other places, but it is
rarely followed. This is largely due to the fact that Java wasn’t designed with
immutability in mind, so it takes a lot of programmer effort to get it.
Still, some popular, high-quality libraries, such as Joda-Time and Google’s collections
library, provide excellent support for programming with immutable data. The fact
that both of these popular libraries provide replacements for functionality available
in Java’s standard library speaks to the usefulness of immutable data.
Thankfully, both Scala and Clojure have much more first-class support for immutable
data, to the extent that it’s often harder to use mutable data than immutable.
model attributes and values. We’ll use a List<String> for our values so that a
single attribute can have multiple values. It returns a String representing the
rendered view.
import java.util.List;
import java.util.Map;
Next we need two classes that are designed to work together using the Strat-
egy pattern: StrategyView and RenderingStrategy.
JavaExamples/src/main/java/com/mblinn/oo/tinyweb/RenderingStrategy.java
package com.mblinn.oo.tinyweb;
import java.util.List;
import java.util.Map;
Now let’s examine the class that delegates to RenderingStrategy, StrategyView. This
class is implemented by the framework and takes care of properly handing
exceptions thrown out of the RenderingStrategy. Its code follows:
JavaExamples/src/main/java/com/mblinn/oo/tinyweb/StrategyView.java
package com.mblinn.oo.tinyweb;
import java.util.List;
import java.util.Map;
@Override
public String render(Map<String, List<String>> model) {
try {
return viewRenderer.renderView(model);
} catch (Exception e) {
throw new RenderingException(e);
}
}
}
We’ll use the Template Method pattern so that users can implement their
own controllers. The central class for this implementation is TemplateController,
which has an abstract doRequest(), as shown in the following code:
JavaExamples/src/main/java/com/mblinn/oo/tinyweb/TemplateController.java
package com.mblinn.oo.tinyweb;
import java.util.List;
import java.util.Map;
try {
Map<String, List<String>> model = doRequest(request);
responseBody = view.render(model);
} catch (ControllerException e) {
responseCode = e.getStatusCode();
} catch (RenderingException e) {
responseCode = 500;
responseBody = "Exception while rendering.";
} catch (Exception e) {
responseCode = 500;
}
return HttpResponse.Builder.newBuilder().body(responseBody)
.responseCode(responseCode).build();
}
protected abstract Map<String, List<String>> doRequest(HttpRequest request);
}
Both the Template Method pattern we used for our controllers and the
Strategy pattern we used for our views support similar tasks. They let some
general code, perhaps in a library or framework, delegate out to another bit
of code intended to perform a specific task. The Template Method pattern
does it using inheritance, while the Strategy pattern does it using composition.
In the functional world, we’ll rely heavily on composition, which also happens
be good practice in the object-oriented world. However, it’ll be a composition
of functions rather than a composition of objects.
Now that we’ve seen all of the pieces of TinyWeb, let’s see how they fit
together.
The TinyWeb class has a single public method, handleRequest(), which takes
HttpRequest. The handleRequest() method then runs the request through the filters,
looks up the appropriate controller to handle it, and returns the resulting
HttpResponse. The code is below:
JavaExamples/src/main/java/com/mblinn/oo/tinyweb/TinyWeb.java
package com.mblinn.oo.tinyweb;
import java.util.List;
import java.util.Map;
if (null == controller)
return null;
return controller.handleRequest(currentRequest);
}
}
A full-featured Java web framework wouldn’t expose a class like this directly
as its framework plumbing. Instead it would use some set of configuration
files and annotations to wire things together. However, we’ll stop adding to
TinyWeb here and move on to an example that uses it.
Using TinyWeb
Let’s implement an example program that takes an HttpRequest with a comma-
separated list of names as its value and returns a body that’s full of friendly
greetings for those names. We’ll also add a filter that logs the path that was
requested.
import com.mblinn.oo.tinyweb.HttpRequest;
import com.mblinn.oo.tinyweb.TemplateController;
import com.mblinn.oo.tinyweb.View;
@Override
public Map<String, List<String>> doRequest(HttpRequest httpRequest) {
Map<String, List<String>> helloModel =
new HashMap<String, List<String>>();
helloModel.put("greetings",
generateGreetings(httpRequest.getBody()));
return helloModel;
}
Next up, let’s take a look at GreetingRenderingStrategy. This class iterates through
the list of friendly greetings generated by the controller and places each into
an <h2> tag. Then it prepends the greetings with an <h1> containing "Friendly
Greetings:", as the following code shows:
JavaExamples/src/main/java/com/mblinn/oo/tinyweb/example/GreetingRenderingStrategy.java
package com.mblinn.oo.tinyweb.example;
import java.util.List;
import java.util.Map;
import com.mblinn.oo.tinyweb.RenderingStrategy;
@Override
public String renderView(Map<String, List<String>> model) {
List<String> greetings = model.get("greetings");
StringBuffer responseBody = new StringBuffer();
responseBody.append("<h1>Friendly Greetings:</h1>\n");
for (String greeting : greetings) {
responseBody.append(
String.format("<h2>%s</h2>\n", greeting));
}
return responseBody.toString();
}
Finally, let’s look at an example filter. The LoggingFilter class just logs out the
path of the request it’s being run on. Its code follows:
JavaExamples/src/main/java/com/mblinn/oo/tinyweb/example/LoggingFilter.java
package com.mblinn.oo.tinyweb.example;
import com.mblinn.oo.tinyweb.Filter;
import com.mblinn.oo.tinyweb.HttpRequest;
@Override
public HttpRequest doFilter(HttpRequest request) {
System.out.println("In Logging Filter - request for path: "
+ request.getPath());
return request;
}
Now that we’ve seen the TinyWeb framework in Java, let’s take a look at how
we’ll use some of the functional replacements for the object-oriented patterns
we’ll explore in this book. This will give us a TinyWeb that’s functionally
equivalent but written with fewer lines of code and in a more declarative,
easier-to-read style.
The biggest change we’ll make is to the view-rendering code. Instead of using
Functional Interface in the form of RenderingStrategy, we’ll use a higher-order
function. We go over this replacement in great detail in Pattern 1, Replacing
Functional Interface, on page 40.
trait View {
def render(model: Map[String, List[String]]): String
}
We start off with our View trait. It defines a single method, render(), which takes
a map representing the data in our model and returns a rendered String.
trait View {
def render(model: Map[String, String]): String
}
Next up, let’s take a look at the body of FunctionView. The code below declares
a class that has a constructor with a single argument, viewRenderer, which sets
an immutable field of the same name.
class FunctionView(viewRenderer: (Map[String, String]) => String) extends View {
«classBody»
}
Next, let’s take a look at the render() method itself. As we can see from the code
below, it takes in a model and runs it through the viewRender() function.
def render(model: Map[String, String]) =
try
viewRenderer(model)
catch {
case e: Exception => throw new RenderingException(e)
}
Notice how there’s no return keyword anywhere in this code snippet? This
illustrates another important aspect of functional programming. In the func-
tional world, we program primarily with expressions. The value of a function
is just the value of the last expression in it.
If we wanted to supply a default value rather than wrap the exception up into
a RenderException, we can do so just by having the appropriate case branch take
on our default, as illustrated in the following code:
try
viewRenderer(model)
catch {
case e: Exception => ""
}
Now when an exception is caught, the try block takes on the value of the
empty string.
In Scala, we rely on function composition just like we did with our views by
passing in a doRequest() function when we create a Controller:
ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/steptwo/Controller.scala
package com.mblinn.mbfpp.oo.tinyweb.steptwo
import com.mblinn.oo.tinyweb.HttpRequest
import com.mblinn.oo.tinyweb.HttpResponse
import com.mblinn.oo.tinyweb.ControllerException
import com.mblinn.oo.tinyweb.RenderingException
trait Controller {
def handleRequest(httpRequest: HttpRequest): HttpResponse
}
try {
val model = doRequest(request)
responseBody = view.render(model)
} catch {
case e: ControllerException =>
responseCode = e.getStatusCode()
case e: RenderingException =>
responseCode = 500
responseBody = "Exception while rendering."
HttpResponse.Builder.newBuilder()
.body(responseBody).responseCode(responseCode).build()
}
}
This code should look fairly similar to our view code. This is a fairly literal trans-
lation of Java into Scala, but it’s not terribly functional because we’re using the
try-catch as a statement to set the values of responseCode and responseBody.
We’re also reusing our Java HttpRequest and HttpResponse. Scala provides a more
concise way to create these data-carrying classes, called case classes.
Switching over to use the try-catch as a statement, as well as using case
classes, can help cut down on our code significantly.
We can create new HttpRequest and HttpResponse objects easily, as the following
REPL output shows:
scala> val request = HttpRequest(Map("X-Test" -> "Value"), "requestBody", "/test")
request: com.mblinn.mbfpp.oo.tinyweb.stepfour.HttpRequest =
HttpRequest(Map(X-Test -> Value),requestBody,/test)
At first glance, this might seem similar to using a Java class with constructor
arguments, except that we don’t need to use the new keyword. However, in
Pattern 4, Replacing Builder for Immutable Object, on page 62, we dig deeper
and see how Scala’s ability to provide default arguments in a constructor,
the natural immutability of case classes, and the ability to easily create a new
instance of a case class from an existing instance lets them satisfy the intent
of the Builder pattern.
Let’s take a look at our second change. Since a try-catch block in Scala has a
value, we can use it as an expression rather than as a statement. This might
seem a bit odd at first, but the upshot is that we can use the fact that Scala’s
try-catch is an expression to simply have the try-catch block take on the value of
the HttpResponse we’re returning. The code to do so is below:
ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/stepthree/Controller.scala
package com.mblinn.mbfpp.oo.tinyweb.stepthree
import com.mblinn.oo.tinyweb.ControllerException
import com.mblinn.oo.tinyweb.RenderingException
trait Controller {
def handleRequest(httpRequest: HttpRequest): HttpResponse
}
class FunctionController(view: View, doRequest: (HttpRequest) =>
Map[String, List[String]] ) extends Controller {
def handleRequest(request: HttpRequest): HttpResponse =
try {
val model = doRequest(request)
val responseBody = view.render(model)
HttpResponse(responseBody, 200)
} catch {
case e: ControllerException =>
HttpResponse("", e.getStatusCode)
case e: RenderingException =>
HttpResponse("Exception while rendering.", 500)
case e: Exception =>
HttpResponse("", 500)
}
}
Rather than tracing the values of responseCode and responseBody from the top of
the method through the try block and finally into the HttpResponse, we only
need to look at the appropriate piece of the try block to understand the final
value of the HttpResponse. These changes combine to give us code that’s more
readable and concise.
Tying It Together
Now let’s add in the class that ties it all together, TinyWeb. Like its Java coun-
terpart, TinyWeb is instantiated with a map of Controllers and a map of filters.
Unlike Java, we don’t define a class for filter; we simply use a list of higher-
order functions!
Also like the Java version, the Scala TinyWeb has a single method, handleRequest(),
which takes in an HttpRequest. Instead of returning an HttpResponse directly, we
return an Option[HttpResponse], which gives us a clean way of handling the case
when we can’t find a controller for a particular request. The code for the Scala
TinyWeb is below:
ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/stepfour/Tinyweb.scala
package com.mblinn.mbfpp.oo.tinyweb.stepfour
class TinyWeb(controllers: Map[String, Controller],
filters: List[(HttpRequest) => HttpRequest]) {
Let’s take a look at it in greater detail starting with the class definition.
class TinyWeb(controllers: Map[String, Controller],
filters: List[(HttpRequest) => HttpRequest]) {
«classBody»
}
Here we’re defining a class that takes two constructor arguments, a map of
controllers and a list of filters. Note the type of the filters argument,
List[(HttpRequest) => HttpRequest]. This says that filters is a list of functions from
HttpRequest to HttpRequest.
Now that we’ve seen the TinyWeb framework, let’s take a look at it in action.
We’ll use the same example from the Java section, returning a list of friendly
greetings. However, since it’s Scala, we can poke at our example in the REPL
as we go. Let’s get started with our view code.
We’ll start by creating a FunctionView and the rendering function we’ll compose
into it. The following code creates this function, which we’ll name greetingViewRen-
derer(), and the FunctionView that goes along with it:
ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/example/Example.scala
def greetingViewRenderer(model: Map[String, List[String]]) =
"<h1>Friendly Greetings:%s".format(
model
getOrElse("greetings", List[String]())
map(renderGreeting)
mkString ", ")
We’re using a couple of new bits of Scala here. First, we introduce the map()
method, which lets us map a function over all the elements in a sequence
and returns a new sequence. Second, we’re using a bit of syntactic sugar that
Scala provides that allows us to treat any method with a single argument as
an infix operator. The object on the left side of the operator is treated as the
receiver of the method call, and the object on the right is the argument.
This bit of syntax means that we can omit the familiar dot syntax when
working in Scala. For instance, the two usages of map() below are equivalent:
scala> val greetings = List("Hi!", "Hola", "Aloha")
greetings: List[java.lang.String]
scala> greetings.map(renderGreeting)
res0: List[String] = List(<h2>Hi!</h2>, <h2>Hola</h2>, <h2>Aloha</h2>)
Now let’s take a look at our controller code. Here we create the handleGreetingRe-
quest() function to pass into our Controller. As a helper, we use makeGreeting(),
which takes in a name and generates a random friendly greeting.
We can create a function and name it by using Scala’s anonymous function syntax,
assigning the resulting function to a val, like we do in this code snippet:
We can almost always use methods as higher-order functions. For instance, here we
pass both the method and the function version of addOne() into map().
Since method definitions have a cleaner syntax, we use them when we need to define
a function, rather than using the function syntax. When we need to manually convert
a method into a function, we can do so with the underscore operator, as we do in the
following REPL session:
scala> addOneMethod _
res3: Int => Int = <function1>
The need to do this is very rare, though; for the most part Scala is smart enough to
do the conversion automatically.
ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/example/Example.scala
def handleGreetingRequest(request: HttpRequest) =
Map("greetings" -> request.body.split(",").toList.map(makeGreeting))
Finally, let’s take a look at our logging filter. This function simply writes the
path that it finds in the passed-in HttpRequest to the console and then returns
the path unmodified:
ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/example/Example.scala
private def loggingFilter(request: HttpRequest) = {
println("In Logging Filter - request for path: %s".format(request.path))
request
}
We can now run the test request through TinyWeb’s handleRequest() method in
the REPL and view the corresponding HttpResponse:
scala> tinyweb.handleRequest(testHttpRequest)
In Logging Filter - request for path: /greeting
res0: Option[com.mblinn.mbfpp.oo.tinyweb.stepfour.HttpResponse] =
Some(HttpResponse(<h1>Friendly Greetings:<h2>Mike</h2>, <h2>Nam</h2>, <h2>John</h2>,
200))
That wraps up our Scala version of TinyWeb. We’ve made a few changes to
the style that we used in our Java version. First, we replaced most of our
iterative code with code that’s more declarative. Second, we’ve replaced our
bulky builders with Scala’s case classes, which give us a built-in way to
handle immutable data. Finally, we’ve replaced our use of Functional Interface
with plain old functions.
Taken together, these small changes save us quite a bit of code and give us
a solution that’s shorter and easier to read. Next up, we’ll take a look at
TinyWeb in Clojure.
The most obvious difference between Clojure and Java is the syntax. It’s very
different than the C-inspired syntax found in most modern programming
languages. This isn’t incidental: the syntax enables one of Clojure’s most
powerful features, macros, which we’ll cover in Pattern 21, Domain-Specific
Language, on page 218.
Like Scala, Clojure has excellent interoperability with existing Java code.
Calling a method on a Java class looks almost exactly like calling a Clojure
function; you just need to prepend the method name with a period and put
it before the class instance rather than after. For instance, this is how we call
the length() method on an instance of a Java String:
=> (.length "Clojure")
7
Instead of organizing Clojure code into objects and methods in Java or into
objects, methods, and functions in Scala, Clojure code is organized into
functions and namespaces. Our Clojure version of TinyWeb is based on
models, views, controllers, and filters, just like the Java and Scala versions;
however, these components will take quite a different form.
Our views, controllers, and filter codes are simply functions, and our models
are maps. To tie everything together, we use a function named TinyWeb,
which takes in all our components and returns a function that takes in an
HTTP request, runs it through the filters, and then routes it to the proper
controller and view.
Controllers in Clojure
Let’s start our look at the Clojure code with the controllers. Below, we implement
a simple controller that takes the body of an incoming HTTP request and uses it
to set a name in a model. For this first iteration, we’ll use the same HttpRequest as
our Java code. We’ll change it to be more idiomatic Clojure later on:
ClojureExamples/src/mbfpp/oo/tinyweb/stepone.clj
(ns mbfpp.oo.tinyweb.stepone
(:import (com.mblinn.oo.tinyweb HttpRequest HttpRequest$Builder)))
(defn test-controller [http-request]
{:name (.getBody http-request)})
(def test-builder (HttpRequest$Builder/newBuilder))
(def test-http-request (.. test-builder (body "Mike") (path "/say-hello") build))
(defn test-controller-with-map [http-request]
{:name (http-request :body)})
Let’s take a look at this code piece by piece, starting with the namespace
declaration.
ClojureExamples/src/mbfpp/oo/tinyweb/stepone.clj
(ns mbfpp.oo.tinyweb.stepone
(:import (com.mblinn.oo.tinyweb HttpRequest HttpRequest$Builder)))
Now let’s take a look at our controller, which takes an HttpRequest from the
original Java solution and produces a Clojure map as a model:
ClojureExamples/src/mbfpp/oo/tinyweb/stepone.clj
(defn test-controller [http-request]
{:name (.getBody http-request)})
Here we call the getBody() method on the HttpRequest to get the body of the
request, and we use it to create a map with a single key-value pair. The key
is the keyword :name, and the value is the String body of the HttpRequest.
Before we move on, let’s look at Clojure maps in greater detail. In Clojure, it’s
common to use maps to pass around data. The syntax for creating a map in
Clojure is to enclose key-value pairs inside curly braces. For instance, here
we’re creating a map with two key-value pairs. The first key is the keyword
:name, and the value is the String "Mike". The second is the keyword :sex, and the
value is another keyword, :male>:
=> {:name "Mike" :sex :male}
{:name "Mike" :sex :male}
Maps in Clojure are functions of their keys. This means that we can call a map
as a function, passing a key we expect to be in the map, and the map will return
the value. If the key isn’t in the map, nil is returned, as the code below shows:
Keywords in Clojure are also functions. When they are passed a map, they
will look themselves up in it, as in the following snippet, which shows the
most common way to look up a value from a map:
=> (def test-map {:name "Mike"})
#'mbfpp.oo.tinyweb.stepone/test-map
=> (:name test-map)
"Mike"
=> (:orange test-map)
nil
Now let’s create some test data. Below, we create an HttpRequest$Builder and use
it to create a new HttpRequest:
ClojureExamples/src/mbfpp/oo/tinyweb/stepone.clj
(def test-builder (HttpRequest$Builder/newBuilder))
(def test-http-request (.. test-builder (body "Mike") (path "/say-hello") build))
This code features two more Clojure/Java interop features. First, the forward
slash lets us call a static method or reference a static variable on a class. So
the snippet (HttpRequest$Builder/newBuilder) is calling the newBuilder() method on the
HttpRequest$Builder class. As another example, we can use this syntax to parse
an integer from a String using the parseInt() method on the Integer class:
=> (Integer/parseInt "42")
42
Next up is the .. macro, a handy interop feature that makes calling a series
of methods on a Java object easy. It works by taking the first argument to ..
and threading it through calls to the rest of the arguments.
The snippet (.. test-builder (body "Mike") (path "/say-hello") build) first calls the body()
method on test-builder with the argument "Mike". Then it takes that result and
calls the path() method on it with the argument "say-hello" and finally calls build()
on that result to return an instance of HttpResult.
Here’s another example of using the .. macro to uppercase the string "mike"
and then take the first character of it:
=> (.. "mike" toUpperCase (substring 0 1))
"M"
Behalve de Hooiwagens onderscheidt men nog een zestal andere familiën (met 150
soorten) van Bastaardspinnen. De zonderlingste vormen treft men aan in het Zuid-
Amerikaansche geslacht Gonyleptes. Het achterlijf is bij deze zoo goed als geheel onder
het stevig gepantserde kopborststuk verborgen. Daarachter steken de ver uiteenwijkende,
breede en zeer lange achterpooten uit, die een bijzonder dikke heup hebben en met
krachtige doornen gewapend zijn. Alleen de mannetjes vertoonen deze afwijkingen; bij
de wijfjes is achter het rugschild van ’t kopborststuk een deel van het achterlijf zichtbaar.
De bruinroode Gonyleptes curvipes bewoont Brazilië en Chili en blijft over dag
verscholen achter boomschors, onder omgehouwen boomstammen, in gaten van den
grond en dergelijke schuilhoeken, waar andere duisterlingen haar tot voedsel dienen.
ZESDE ORDE.
DE ECHTE SPINNEN (A r a n e i n a ).
In ’t oog vallende eigenaardigheden van de Spinnen zijn haar arglistig loeren op buit van
uit een verborgen hinderlaag en de alles behalve vriendschappelijke betrekking, waarin
zij, vooral het mannetje en het wijfje, tot elkander staan. Om de hevigste openbaring van
vijandschap tusschen twee menschen aan te duiden, vergelijkt men hen met Spinnen.
Daar hare uitwendige kenteekenen al even weinig innemend zijn als de beide reeds
genoemde karaktertrekken, worden de Spinnen door de meeste menschen gemeden en
verafschuwd, hoewel zij in vele opzichten onze bewondering verdienen. Haar
lichaamsbouw is niet minder merkwaardig dan die der overige Arthropoden; haar arbeid
heeft evenveel aanspraak op onze waardeering. Reeds door de ouden werd dit erkend.
Volgens een Grieksche sage had A r a c h n e , de dochter van den purperverwer
I d m o n , die van P a l l a s - A t h e n e de weefkunst had geleerd, de onbescheidenheid
om aan haar goddelijke leermeesteres een wedstrijd voor te stellen. Te vergeefs werd dit
waagstuk haar ontraden door de godin, die de gedaante van een oude vrouw had
aangenomen. A r a c h n e bleef bij haar voornemen en vervaardigde een kunstig weefsel,
dat de minnarijen der goden voorstelde. Toen A t h e n e , hierover vertoornd, het weefsel
verscheurde, hing A r a c h n e uit wanhoop zich op. De godin riep haar in ’t leven terug
in de gestalte—van een Spin, opdat zij naar welgevallen zou kunnen hangen.—Koning
Salomo stelde de Spin tot voorbeeld aan zijne hovelingen wegens haar vlijt,
kunstvaardigheid, schranderheid, matigheid en deugd.
K r u i s s p i n (Epeira diadema):—1) Wijfje. 2) Mannetje. 3) Spinpijpje. 4) Spintepels met de aarsopening
(boven) en het „zeefje” (onder). 5) Kaaksprieten en oogen. 6) Linker kaakspriet, waarvan het grondlid
overlangs doorgesneden is om de gifklier in haar geheel te toonen. 7) Top van het voetlid.—3–7 sterk vergr.
De hardheid van de chitinelaag, die het lichaam van de Spin bedekt, is zeer ongelijk; bij
de inheemsche soorten is zij over ’t algemeen zachter dan bij verscheidene
buitenlandsche, waaronder er zijn met een zeer harde schaal. Na de klauwen hebben
altijd het rugschild en het borstschild van het kopborststuk de grootste hardheid. De
oppervlakte is niet meer of minder dicht bekleed met lange, borstelige of korte
fluweelachtige haren, soms ook met stekels; niet zelden verhoogt dit kleed in niet
geringe mate het afschrikwekkend voorkomen van de Spinnen. Sombere kleuren hebben
bij haar gewoonlijk de overhand; niet zelden echter zijn zij lichter en bont van kleur en
teekening. Voor de onderscheiding der soorten zijn deze verschijnselen niet zeer
geschikt.
Daar de Spinnen van roof, n.l. van allerlei Insecten, leven, is, evenals aan andere
roofdieren, gezelligheid haar vreemd; zij moeten hare soortgenooten mijden en in
sommige gevallen bestrijden. De uitzonderingen op dezen regel zijn zeldzaam en alleen
in Zuid-Afrika en Argentinië waargenomen.
De Spinnen zijn arme wevers; evenals deze, moeten zij weven, om in hun
levensonderhoud te voorzien; zij moeten echter spaarzaam zijn met de grondstof, omdat
deze bij goede voeding in ruime mate, bij schralen kost slechts in geringe hoeveelheid
beschikbaar is. De draad, die het lichaam verlaten heeft, kan er niet weer in
teruggetrokken worden. Soms zou men kunnen meenen, dat dit wel geschiedt, n.l. als de
Spin bij een draad naar boven klimt en deze daarbij steeds korter wordt; in dit geval
echter wordt de draad eenvoudig opgewikkeld en aan de pooten medegevoerd. Een nog
veel grooter onderscheid dan er bij verschillende soorten van Wespen wordt
waargenomen in de wijze van bouwen der nesten, merkt men bij de Spinnen op.
Sommige, zooals de van oudsher bekende Kruisspin, vervaardigen een wielvormig web,
andere, zooals de Gewone Huisspin, een dichter weefsel van trechtervormige gedaante,
nog andere buizen, zakken, enz., hieraan danken zij de namen Wiel-, Kruisnet-,
Trechter-, Zakspinners. Een groot aantal Spinnen vangen haar prooi niet in een web,
maar oefenen op een eerlijker wijze het roovershandwerk uit door het Insect, dat in de
nabijheid van haar schuilhoek komt, loopend te vervolgen of onverhoeds te bespringen.
Bovendien gebruiken de Spinnen hare draden als middel om van plaats te veranderen; zij
laten zich spinnend naar beneden zakken en kunnen ook, door de draad in
schommelende beweging te brengen, een voorwerp bereiken, dat niet onmiddellijk onder
haar uitgangspunt gelegen is. Wanneer de draad van hier losgerukt en door
luchtstroomingen medegevoerd wordt, zal zij een kleine Spin kunnen dragen; bij fraai
herfstweder ziet men sommige soorten op deze wijze door de lucht vliegen en zich over
een grooten afstand verplaatsen. Alle Spinnen zonder uitzondering, voor zoover zij
wijfjes zijn, gebruiken het product van hare spinklieren tot beschutting van de eieren.
Deze overigens zoo wreedaardige dieren leveren sterk sprekende bewijzen van
moederliefde en overtreffen in dit opzicht zelfs de Insecten, die het best voor hunne
jongen zorgen. De eieren worden meestal midden in den zomer gelegd; bij gunstige
temperatuur en vochtigheidstoestand van de lucht verlaat het jong 3 à 4 weken later het
ei. De meeste Springspinnen, Zak-, Trechter- en Wielspinners leggen in het laatst van
den zomer eieren en brengen het gewoonlijk lensvormige, soms halfbolvormige nestje
op een voor winterkwartier geschikte plaats. Van de leden dezer familiën overwinteren
slechts bij uitzondering enkele exemplaren; daarentegen verkeeren de nog niet
volwassen jongen van de overige soorten des winters op hunne gewone schuilplaatsen in
een toestand van verstijving. In het gunstige jaargetijde groeien zij tamelijk snel, hetgeen
door verscheidene vervellingen mogelijk wordt. Over ’t algemeen is men van oordeel,
dat bij de vierde vervelling de groei ophoudt en dat na dien tijd de vervanging van
verloren lichaamsdeelen niet meer voorkomt.
Het aantal bekende soorten van Spinnen bedraagt eenige duizenden en neemt nog steeds
toe. Zij zijn over de geheele aardoppervlakte verbreid; sommige soorten worden nog op
een hoogte van ongeveer 3125 M. boven den zeespiegel aangetroffen. Toch zijn warme
landen beter voor haar ter bewoning geschikt dan koudere, zooals blijkt uit de grootere
verscheidenheid van vormen, die deze orde in de tropische gewesten aanbiedt; hier leven
de grootste en fraaiste soorten. In het barnsteen zijn overblijfselen van een niet
onbelangrijk aantal uitgestorven soorten (ongeveer 250) gevonden. Reeds in de
steenkolenformatie bestond deze orde; twee soorten uit dit tijdperk zijn bekend.
Vo g e l s p i n (Mygale).
De Indianen vreezen de Boschspin niet. Bates zag de kinderen, die voor hem Insecten
verzamelden, met een groot dier van deze soort spelen. Zij hadden het een draad om het
lichaam gebonden en liepen er mede door het huis als met een hondje.
In 1862 werd te Danzig bij het lossen van een uit Engeland afkomstig kolenschip een
levende Mygale avicularia gevonden en bijna een jaar lang in ’t leven gehouden. Zij
verslond Insecten, Pissebedden en Spinnen, maar ook Kikvorschen en rauw vleesch.
De Vogelspin is pekzwart en met zwartbruine haren bekleed; een koperkleurig rood vilt
bedekt het breede, platgedrukte eindlid van den poot, dat twee verborgene, ongetande
klauwen draagt; de voorste middeloogen zijn aanmerkelijk grooter dan de overige. De
leden van het soortenrijke geslacht Mygale onderscheiden zich door de X-vormige
rangschikking der 8 dicht bijeen geplaatste oogen, door stevige, lang en dicht behaarde
pooten en door twee gekromde haken aan het einde van het tweede scheenlid van de
voorpooten.
Bij Mygale en een gering aantal andere geslachten vindt men 4 longzakken, dus ook 4
ademgaten aan ’t voorste deel van den buik (alle overige leden der orde bezitten 2
longen), s l e c h t s v i e r spintepels, waarvan 2 zeer klein zijn, en naar voren gerichte
kaaksprieten, welker klauwlid b e n e d e n w a a r t s en niet binnenwaarts tegen het
grondlid wordt aangelegd. De Spinnen, die deze kenmerken gemeen hebben, worden
gezamenlijk V i e r l o n g i g e n (Tetrapneumones) genoemd. In Europa is deze groep
o.a. vertegenwoordigd door de M e t s e l s p i n n e n (Cteniza), waarvan 6 soorten het
Middellandsche Zee-gebied bewonen en door het geslacht Atypus (d.i. „afwijkend”, zoo
genoemd wegens het bezit van 6 spintepels), waarvan 3 soorten, behalve in Zuid-Europa,
ook, hoewel zelden, in Duitschland gevonden worden.
Alle Spinnen, die slechts door t w e e longen (sommige bovendien door luchtbuizen)
ademen—de T w e e l o n g i g e n (Dipneumones)—, hebben het klauwvormig eindlid
van de kaaksprieten in rust binnenwaarts gericht. Op grond van haar levenswijze kan
men ze verdeelen in G e v e s t i g d e of W e b s p i n n e n (Sedentariae) en
Z w e r v e n d e of J a c h t s p i n n e n (Vagaebundae). De laatstgenoemde maken geen
web en vangen loopend of springend haar buit; de eerstgenoemde wachten hem af op of
bij het web, dat zij vervaardigen, of de draden, die zij spannen, en worden, naar de wijze
van spinnen, in verscheidene familiën verdeeld.
Dit alles kan men het gemakkelijkst waarnemen bij de algemeen bekende G e w o n e
K r u i s s p i n (Epeira diadema). Aan de rugzijde van het vette, glanzige achterlijf ziet
men lichte vlekjes een kruis vormen op den lichter of donkerder bruinen, met meer of
minder grijs gemengden ondergrond; dit heeft aanleiding gegeven tot den naam. Andere
hier voorkomende, meestal zuiver witte vlekken en stippels, begrenzen een driehoekig
veld. Bij het aanmerkelijk kleinere, slechts 11 mM. lange mannetje zijn de schenen van
de 2e paar pooten verdikt. De Epeiren spinnen uit 6 tepels met zeer talrijke pijpjes.
De Gewone Kruisspin wordt in ’t grootste deel van Europa in tuinen, kreupelhout en ijle
naaldhoutbosschen gevonden; meestal vestigt zij zich op betrekkelijk geringen afstand
van den grond, bij voorkeur in de nabijheid van slooten, moerassen, meren, kortom op
plaatsen waar Vliegen en Muggen gewoonlijk in overvloed rondvliegen. In ’t begin van
Mei verlaten de jongen de eischaal; gedurende ongeveer 8 dagen blijven zij bijeen, of
liever komen telkens weer samen na zich verspreid te hebben; na de eerste vervelling
verlaten zij haar geboorteplaats. Langzamerhand, na verscheidene vervellingen
ontwikkelt zich de teekening, die het volwassen dier onder de fraaiste inheemsche
soorten een plaats verschaft. Zoodra de jonge Kruisspinnen zich verstrooid hebben, spint
ieder een web, dat natuurlijk wegens zijn geringe grootte minder de aandacht trekt dan
de wielvormige weefsels van 30 en meer cM. middellijn, welke men later ontmoet. De
plaats waar zij zich vestigen zal, wordt eerst na rijp beraad bepaald; voordat zij aan den
arbeid tijgt, loopt zij geruimen tijd op allerlei voorwerpen rond; dit is volstrekt noodig,
daar zij op deze plaats op een andere wijze te werk moet gaan dan op gene om de
buitendraden te spannen, die het drie- of vierhoekige raam begrenzen, waaraan het web
bevestigd is. Haar eerste werk bestaat in het vasthechten van den draad, dien zij zal
spinnen, door drukking met de spits van het achterlijf; in verreweg de meeste gevallen
geschiedt dit op een hoog gelegen plaats. Zij laat deze los en zakt langzamerhand door
haar eigen gewicht, hangend aan den steeds langer wordende, uit de spintepels
komenden draad, die vervolgens in strak gespannen toestand bevestigd wordt; het
tweede aanhechtingspunt is steeds lager gelegen dan het eerste. Groote zorgvuldigheid
vereischt het spinnen van den bovensten dwarsdraad, die als een strak gespannen touw
twee soms ver uiteenliggende punten verbindt. Wanneer het niet mogelijk is te voet van
het eene punt naar het andere te komen, schiet de Spin een draad uit, die door
luchtstroomingen naar het tweede aanhechtingspunt wordt vervoerd; soms laat zij zich,
onder aan een draad hangend, zoo lang heen en weer slingeren, totdat zij met de pooten
de gewenschte plaats bereiken kan. Indien de draad niet dadelijk de noodige spanning
heeft, wordt hij door korte zijdraden strak getrokken. Als het raam gereed is, verbindt de
Spin twee tegenovergestelde punten door aan het eene een draad te bevestigen, langs de
buitendraden naar het andere punt te loopen en intusschen den steeds langer wordende
nieuwen draad met den achterpoot van zich af te houden. Door tusschen het midden
dezer lijn en den omtrek heen en weer te gaan komen de spaken van het wiel tot stand,
waarbij de laatste verkregene steeds als weg dient bij het spinnen van de volgende. De
nu volgende arbeid, het verbinden van alle stralen door cirkels, levert geen bezwaar op.
In het middelveld, dat zich ongeveer zoo ver uitstrekt, als de Spin hare pooten kan
uitsteken, zijn deze draden droog, evenals de tot dusver gebruikte; verderop zijn zij bezet
met zeer talrijke, buitengewoon fijne, kleverige knobbeltjes en hierdoor in staat om
denzelfden dienst te doen als de lijmroeden bij het vogelvangen: zij houden de vliegende
Insecten vast, die er mede in aanraking komen. Men heeft uitgerekend, dat een web van
36 à 39 cM. middellijn ongeveer 120 000 van deze knobbeltjes bevat.
Het nu voltooide werkstuk levert een sterk sprekend bewijs van de buitengewone
kunstvaardigheid der Spin; de stralen en cirkels, hoewel minder zuiver van constructie
dan die van den met liniaal en passer uitgerusten teekenaar, vormen te zamen een
bewonderenswaardig geheel. Met lofwaardigen ijver is deze arbeid verricht; vooral na
een zachte regenbui wordt er gewoonlijk slechts één dag of één nacht aan besteed. Met
omlaag gericht kopborststuk troont op ’t middelveld de kunstenares. Soms acht zij het
verkieselijker aan den buitenkant van haar web onder een blad of op een andere
beschutte plaats haar hoofdkwartier te vestigen; steeds is dit plekje met het middelpunt
van het wiel verbonden door eenige sterk gespannen draden, die als telegraaf dienst
doen, van iedere beweging van het web terstond kennis geven. Zij geraken in trilling
door de onbesuisde Vlieg, die het ongeluk had met het net in aanraking te komen en bij
hare pogingen om zich te bevrijden hoe langer hoe meer in de draden verward geraakt.
Niet in eens, maar bij rukken schiet de Spin van uit de hinderlaag op haar slachtoffer toe;
zij is altijd voorzichtig, gaat nooit met blinde overhaasting te werk. Eerst begeeft zij zich
naar het middelpunt en van hier naar de plaats waar de Vlieg, door geweldig te spartelen
en te gonzen, hare krachten verspilt. Een beet met de gifkaken brengt haar spoedig tot
rust. De Spin zal, indien zij zeer hongerig is, onmiddellijk na de vangst den buit
verslinden, maar dezen, bij minder groote behoefte aan voedsel, met een breeden band
van draden omwikkelen. Als een pop in een cocon, blijft het goed ingepakte slachtoffer
voorloopig hangen; ter gelegener tijd bijt de Spin den opgespaarden voorraad los en
vervoert dezen naar haar schuilplaats; hier gaat zij op haar gemak aan ’t kauwen, waarna
de met speeksel tot een brijachtige massa verwerkte prooi opgezogen wordt. Als een
Wesp of een dergelijk onbruikbaar dier in het web geraakt, zal de Spin zelf door het stuk
bijten van eenige draden tot de bevrijding van de gevangene medewerken. Soms zit het
web vol van kleine Mugjes, die nagenoeg geen voedsel opleveren, maar door hun
donkere kleur en door het bedekken van de kleverige knobbeltjes der draden de
bruikbaarheid van het vangtoestel zoo zeer verminderen, dat de Spin zich genoodzaakt
ziet een ander web te vervaardigen. Onze Kruisspin heeft geen helpsters zooals sommige
van hare West-Indische verwanten, in welker web Darwin dikwijls kleinere spinnetjes
aantrof, die, naar hij vermoedt, op de gevangene Insecten azen, die wegens hun geringe
grootte door de eigenares van het web versmaad worden. Dat de Kruisspin haar weefsel
herstelt, wanneer het beschadigd is, wordt door sommige onderzoekers beweerd, door
andere betwist; waarschijnlijk geschiedt dit alleen op plaatsen, die zoo gunstig gelegen
zijn voor de vangst, dat de Spin geen lust gevoelt ze te verlaten.
De omstandigheden bepalen de wijze, waarop de Spin te werk gaat, zoowel bij het
aanleggen van het raam voor haar web als bij de behandeling en het verslinden van den
buit; evenals in deze gevallen, toont zij ook overleg bij de keuze van maatregelen, om
aan een dreigend gevaar te ontkomen. Haar gewone redmiddel is, zich te laten zakken
aan een draad; soms acht zij het blijven hangen in de lucht voldoende; soms echter daalt
zij tot op den bodem af en houdt zich dood; zoodra het gevaar geweken is, keert zij langs
den draad naar haar vroegere zitplaats terug. In andere gevallen van verontrusting blijft
zij stevig vastgehecht zitten op het middelveld van haar web, maar deelt hieraan zulk een
hevige, trillende beweging mede, dat men haar lichaam niet meer kan onderscheiden. In
den herfst zijn de Kruisspinnen volwassen. In een streek waar deze dieren talrijk zijn,
schat men het aantal wijfjes op 10 à 15 tegen 1 mannetje. Het mannetje heeft een eigen
web en toont gedurende de kortstondige spinnenvrijage een niet ongegronde vrees voor
zijn veel grootere wederhelft. In September of October legt het wijfje ongeveer 100 gele
eieren in een door haar gesponnen zakje, dat zij op een veilige plaats ophangt. De
omvang van haar achterlijf vermindert hierdoor zoo sterk, dat zij bijna onkenbaar wordt.
Zij sterft vóór den aanvang van den winter, maar blijft tot aan het einde van haar leven
hare eieren zorgvuldig bewaken. Zelden treft men in den winter onder boomschors of
mos Gewone Kruisspinnen aan; steeds zijn dit onvolwassene exemplaren, die later dan
gewoonlijk (Mei) de eischaal verlieten.
In de warme landen van beide halfronden, in Amerika tot in den staat Ohio, leven
talrijke, tot verschillende geslachten behoorende soorten van Wielspinners, die zich
kenmerken door een hoornachtig, van achteren in twee lange, rechte of kromme doornen
eindigend rugschild op het achterlijf. Tot de meest verbreide behoort het geslacht der
D o o r n s p i n n e n (Gasteracantha), dat nog wel zonderlinger vormen omvat dan de
hierna afgebeelde T a n g v o r m i g e D o o r n s p i n (Gasteracantha arcuata), die op
Java gevonden wordt.
Sommige K r u i s n e t s p i n n e r s (Theridiidae—meer bepaaldelijk de Linyphiinae en
de Theridiinae) spinnen in de struiken of tusschen grashalmen een horizontaal,
dekenvormig web, welks draden elkander in alle richtingen kruisen. O n d e r dit nest
wonen in den paartijd de mannetjes en de wijfjes gezellig bijeen; in de overige tijden van
’t jaar leeft ieder afzonderlijk. Andere leden van dezelfde familie spinnen enkele draden
in verschillende richtingen, overlangs, overdwars, naar boven, naar onderen, of werpen
er een uit onder het loopen, maar vervaardigen geen echt web (Pachygnathinae); evenals
de zoogenaamde Jachtspinnen (Vagabundae), vangen zij hun prooi loopend of
springend. Bij de leden der eerstgenoemde afdeeling zijn er, die onder hun met een
troonhemel vergelijkbaar weefsel nog een klein, horizontaal, wielvormig web
vervaardigen en bovendien een klein, klokvormig broeinestje, waarin het wijfje één of
eenige eierenhoopjes bewaakt. Al deze Spinnen zijn gewoon om, aan de pooten, met
naar beneden gekeerden rug, o n d e r haar net hangend, haar buit af te wachten. De
meeste hebben een zeer bol, bijna kogelvormig achterlijf; de pooten zijn dun en lang; de
voorste steeds de langste.
De genoemde soort komt in vorm ongeveer met de Oeverspin overeen, hoewel zij in rust
aan hare pooten een geheel andere richting geeft en veel kleiner is; haar lengte bedraagt
5 à 7 mM. Het kopborststuk is bruin, aan de zijden met donkerder randen; het achterlijf
prijkt op witten grond met een langwerpig, bruin schild, dat een donkerder, gehakkelden
zoom heeft; de buik is donkerbruin met 4 witte vlekken. De geelachtige pooten hebben
op de dij en de scheen en aan den achtervoet 2 zwartbruine ringen, één bovendien aan de
uiteinden der knieën en aan de leden der overige voeten.
Als de Huisspin haar nest begint te bouwen, drukt zij het spinveld op een afstand van
eenige cM. van den hoek tegen den eenen muur, wandelt naar den anderen, intusschen
een draad spinnend, die zij hier, ongeveer op denzelfden afstand van den hoek als
zooeven, vasthecht, na haar strak gespannen te hebben. Daar zij de buitenste en
belangrijkste draad is, wordt haar dikte achtereenvolgens verdubbeld en verdrievoudigd.
Door het aanhoudend heen-en-weer loopen langs dit samenstel van 3 draden en de steeds
korter wordende, die hieraan achtereenvolgens verder naar binnen in onderling
evenwijdige richting worden toegevoegd, ontstaat de „ketting”, die met de haar
kruisende, als „inslag” dienende dwarsdraden het vangweb vormen, dat in het midden
een weinig hol staat. Hiermede is echter het geheele kunstwerk nog niet voltooid. Voor
zich zelf weeft de Spin nu achter in den hoek een aan beide einden geopende buis,
waaraan, als aan een korten steel, het vroeger vervaardigde, driehoekige net vastgehecht
is. Daar zij zich bij voorkeur vestigt op plaatsen waar gaten en spleten in den muur
voorkomen, mondt de buis in zulk een gat uit, waarin de Spin bij naderend gevaar zich
verschuilt. In ’t voorste gedeelte van deze buis loert zij op buit; de op het net komende
Vlieg of Mug wordt onmiddellijk gegrepen en naar haar hinderlaag vervoerd, waar zij
het slachtoffer op haar gemak verslindt.
Iedere Spin moet spaarzaam zijn met de stof, waarvan zij haar web spint, omdat de
beschikbare voorraad afhangt van de hoeveelheid voedsel, die haar ten deel valt, en dus
geringer is bij een uitgehongerd dan bij een goed doorvoed exemplaar; daarom spint zij
niet, wanneer storm of regen haar arbeid onmiddellijk weder kunnen vernielen en dus
nutteloos maken. In verband hiermede zijn de Spinnen zeer gevoelig voor
weersveranderingen. Men heeft ze zelfs tot het voorspellen van een toekomstige
weersgesteldheid in staat geacht en deze trachten af te leiden uit het werken of rusten, te
voorschijn komen of zich verbergen van de Spinnen, uit haar houding in het web, uit de
meerdere of mindere stevigheid, die zij geven aan de buitendraden van haar nest, uit het
vervaardigen van nieuwe of het vergrooten van reeds bestaande weefsels, enz. Vooral op
de handelingen van de Kruisspin en de Huisspin heeft men acht gegeven. Als de
Kruisspin eenige van de buitendraden van haar web verscheurt en vervolgens een
schuilplaats opzoekt, als de Huisspin of een andere Trechterspin, enz. zich diep in haar
buisvormige woning begeeft, wordt in ’t eene geval op de ligging der bedoelde draden,
in ’t andere op de richting van de spits van het achterlijf gelet en hieruit afgeleid, dat er
weldra een hevige wind uit dien hoek zal waaien. Wanneer echter de Huisspin de draden
van het raam van haar web herstelt en een afwachtende houding aanneemt, als de
Huisspin en hare verwanten met buitenwaarts gericht kopgedeelte aan den ingang van
haar woning verschijnen en de pooten strekken, alsof zij zich gereed maken een prooi te
bespringen, verwacht men verbetering van de weersgesteldheid. Tot staving van de
bedoelde voorwetenschap der Spinnen wordt gewoonlijk gewezen op een gebeurtenis,
die in het jaar 1794 aan het Fransche leger, dat Holland trachtte te bezetten, de zege
verschafte. De Fransche bevelhebber Pichegru was van oordeel, dat hij tegen de door
onderwaterzettingen beschermde stellingen van het Hollandsche leger niets zou kunnen
uitrichten en stond op het punt onverrichter zake terug te keeren, toen hij van den te
Utrecht gevangen gehouden generaal-adjudant Quatremère d’Isjonval het op
waarnemingen aan Spinnen gegronde bericht ontving, dat men binnen 10 dagen op vorst
kon rekenen. Pichegru bleef, de voorspelde weersverandering had plaats en het
Fransche leger kon over het ijs tot Amsterdam doordringen. Nauwgezette
onderzoekingen hebben geleerd, dat men geen staat kan maken op dergelijke
voorspellingen, al komen zij toevalligerwijze een enkele maal uit. Het is mogelijk, dat de
Spin aan verschijnselen, die aan onze zintuigen ontgaan, een r e e d s i n g e t r e d e n
verandering van den toestand der atmosfeer opmerkt; stellig bezit zij echter geen
profetische gave, die haar in staat stelt om dagen van te voren over het komende weer te
oordeelen.
Spinrag—vooral dat van de Huisspin, daar dit het gemakkelijkst kan worden verkregen
—behoort ook tot het tallooze heir van middelen, die tot het bestrijden van
ziekteverschijnselen aangewend worden of werden; naar men beweert, helpt het tegen
afwisselende koorts. Algemeener bekend is de bloedstelpende werking van
spinnewebben, die op een wonde gelegd zijn; niet zelden echter heeft het toepassen van
dit middel, wegens den onvoldoende staat van zuiverheid waarin het verkeerde,
aanleiding gegeven tot verergering van de kwaal. Ook heeft men getracht spinrag als
zijde te verwerken; het ligt echter voor de hand, dat de productie van een dergelijke, van
een roofdier afkomstige grondstof, nooit voldoende zal kunnen zijn om hierop een
voordeel afwerpende industrie te gronden.
De beide genoemde en eenige verwante geslachten worden onder den naam van
T r e c h t e r s p i n n e r s (Ageleninae) tot een onderfamilie vereenigd, die zich o.a.
kenmerkt door het bezit van een bijklauw met 8 à 5 tanden. Een andere afdeeling van de
familie der B u i s s p i n n e r s (Tubitelae) vormen de Z a k s p i n n e r s (Drassinae);
deze hebben een rolrond of langwerpig eivormig achterlijf en korte pooten, waaraan de
bijklauw meestal ontbreekt.
Deze Spin leeft bijna voortdurend in ’t water en ademt door longen en tracheën te gelijk.
Op haar uiterlijk afgaande, zou men haar licht kunnen verwarren met andere soorten van
Spinnen, van welke zij zich echter aanmerkelijk onderscheidt door haar levenswijze. Zij
bewoont stilstaand of langzaam stroomend water, dat rijk is aan Mijten en kleine
Insecten, aan eendenkroos en verschillende andere waterplanten; hier zwemt zij en
bouwt er haar nest. Zij kan echter gedurende korten tijd buiten haar element leven. De
zwemmende Spin levert een verrassend schouwspel op, daar haar achterlijf omgeven is
door een dunne luchtlaag, die als een druppel kwikzilver glinstert (haar geslachtsnaam
beteekent „met zilver omspannen”). Deze luchtlaag verraadt de aanwezigheid van het
diertje, dat anders wegens zijn kleinheid licht onopgemerkt zou blijven; zij wordt niet
alleen door de fluweelachtige beharing vastgehouden, die het natworden van de huid
verhindert, maar bovendien door een soort van vernis van het omgevende water
gescheiden.
Wanneer deze kleine duikkunstenares een nest wil bouwen, begeeft zij zich naar den
waterspiegel en steekt, op den kop staande, met naar boven gerichten buik, de spits van
haar achterlijf boven de oppervlakte in de lucht, spreidt de spintepels uit en daalt
schielijk weer in ’t water af. Zoodoende neemt zij, zonder dat het zilveren omhulsel van
het achterlijf er bij te pas komt, een meer of minder groote, aan de spits van ’t lichaam
hangende luchtbel mede. Deze wordt zwemmend vervoerd naar de waterplant, die bij
een vroeger bezoek geschikt werd geoordeeld voor ’t bouwen van een woning en hier
vastgehecht. Dit vereischt natuurlijk het gebruik van spinstof, die, uit de spintepels
ontwijkend, als een soort van vernis, dat met de achterpooten wordt uitgestreken, de
lucht van het water scheidt, daar deze anders onmiddellijk weer naar boven zou stijgen.
Opnieuw gaat zij een luchtbel halen, die na doelmatige vergrooting van het reeds
aanwezige spinsel met de eerste samenvloeit; deze arbeid wordt voortgezet, totdat de
kleine, met de opening naar beneden gerichte duikerklok ongeveer de grootte van een
walnoot bereikt heeft. Verscheidene draden moeten natuurlijk gedurende het bouwen
gespannen worden om aan het nest de vereischte stevigheid te verschaffen. Andere, die
rondom den ingang zich in alle richtingen uitspreiden, dienen als valstrikken voor den
zwemmenden buit. Indien de Spin hare slachtoffers afwachtte, zou zij menigmaal honger
moeten lijden; zij gaat ze echter ook wel opzoeken en houdt zich niet strikt aan één
bepaalde wijze van jagen gelijk hare verwanten, die in de lucht vangwebben hebben.
Zoodra zij een prooi gegrepen heeft, kruipt zij bij den eersten den besten stengel omhoog
en verslindt het lekkere hapje in de lucht; soms kiest zij tot eetzaal haar duikerklok, of
hangt hierin het overschot voor toekomstig gebruik op, zoodra haar honger gestild is. In
de gevangenschap bevestigt de Waterspin haar duikerklok ook wel aan den wand van het
glas, waarin zij leeft.
Het wijfje legt eieren in een luchtbel, die, met een dubbele laag spinsel omkleed en tot
een min of meer platbol zakje vervormd, aan een waterplant of in de duikerklok
opgehangen en zorgvuldig bewaakt wordt.
Een groot aantal over verschillende geslachten verdeelde Zakspinnen leven verborgen
onder steenen, in mos, in spleten van muren en rotsen en achter schorsschilfers van oude
boomen. Op de laatstgenoemde plaats merkt men dikwijls wit zijden lichaampjes op, die
op hemdsknoopjes gelijken, in ’t midden een weinig uitpuilen en een vlakken rand
hebben; verscheidene soorten van Zakspinnen maken zulke eiernestjes; hun platte zijde
is vastgekleefd aan de binnenzijde van de schorsschilfers of tegen den ontschorsten
stam; ook vindt men ze wel in opgerolde bladen. Een van de meest verbreide soorten
dezer afdeeling, de A t l a s s p i n (Clubiona holosericea), wordt, behalve in tuinen, waar
zij de genoemde schuilhoeken bewoont, niet zelden ook in huizen gevonden.
Zeer algemeen vindt men onder steenen, boomschors of mos, in gaten van muren, in
kelders en in stroodaken de 10 à 11 mM. lange K e l d e r s p i n (Segestria senoculata);
zij bewoont een middelmatig lange, witte, aan weerszijden geopende buis, van waar zij
in verschillende richtingen draden spant om Insecten te vangen. Aan den ingang dezer
buis zit zij op de loer, houdt de 6 voorste pooten naar voren gericht en het lichaam tegen
den wand gedrukt. Het in de vangdraden verschijnende slachtoffer wordt onmiddellijk
gegrepen en medegenomen naar het achterste deel van de buis. Koen en behendig valt zij
Insecten aan, die haar door grootte en kracht verre overtreffen; zelfs voor Wespen, die
door de meeste andere Spinnen gevreesd worden, deinst zij niet terug. In het midden van
den zomer verlaten de jongen het nagenoeg bolvormige eierenzakje en houden zich
aanvankelijk in het nest van de moeder op. De Kelderspin heeft een betrekkelijk slanke
gedaante; het langwerpig eivormige, glanzig zwartbruine kopborststuk is bijna dubbel
zoo lang als breed; het bruinachtig gele achterlijf is behaard en op den rug met een reeks
van 6 donkerbruine vlekken getooid.—Een van hare naaste verwanten is de op Cuba
onder steenen levende Nops Guanabacoae, die door het bezit van slechts 2 oogen een
merkwaardige uitzondering vormt op den voor alle overige Spinnen geldenden regel.
ebookgate.com