100% found this document useful (2 votes)
34 views

PDF Learning Functional Data Structures and Algorithms Learn functional data structures and algorithms for your applications and bring their benefits to your work now 1st Edition Atul S. Khot download

bring

Uploaded by

dolbyzdruey
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
34 views

PDF Learning Functional Data Structures and Algorithms Learn functional data structures and algorithms for your applications and bring their benefits to your work now 1st Edition Atul S. Khot download

bring

Uploaded by

dolbyzdruey
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 55

Experience Seamless Full Ebook Downloads for Every Genre at textbookfull.

com

Learning Functional Data Structures and Algorithms


Learn functional data structures and algorithms
for your applications and bring their benefits to
your work now 1st Edition Atul S. Khot
https://textbookfull.com/product/learning-functional-data-
structures-and-algorithms-learn-functional-data-structures-
and-algorithms-for-your-applications-and-bring-their-
benefits-to-your-work-now-1st-edition-atul-s-khot/

OR CLICK BUTTON

DOWNLOAD NOW

Explore and download more ebook at https://textbookfull.com


Recommended digital products (PDF, EPUB, MOBI) that
you can download immediately if you are interested.

Learning functional data structures and algorithms learn


functional data structures and algorithms for your
applications and bring their benefits to your work now
Khot
https://textbookfull.com/product/learning-functional-data-structures-
and-algorithms-learn-functional-data-structures-and-algorithms-for-
your-applications-and-bring-their-benefits-to-your-work-now-khot/
textboxfull.com

Probabilistic data structures and algorithms for big data


applications Gakhov

https://textbookfull.com/product/probabilistic-data-structures-and-
algorithms-for-big-data-applications-gakhov/

textboxfull.com

Data Structures and Algorithms in Swift Kevin Lau

https://textbookfull.com/product/data-structures-and-algorithms-in-
swift-kevin-lau/

textboxfull.com

Data Structures & Algorithms in Python John Canning

https://textbookfull.com/product/data-structures-algorithms-in-python-
john-canning/

textboxfull.com
A Common Sense Guide to Data Structures and Algorithms 1st
Edition Jay Wengrow

https://textbookfull.com/product/a-common-sense-guide-to-data-
structures-and-algorithms-1st-edition-jay-wengrow/

textboxfull.com

Data Structures Algorithms in Kotlin Implementing


Practical Data Structures in Kotlin 1st Edition
Raywenderlich Tutorial Team
https://textbookfull.com/product/data-structures-algorithms-in-kotlin-
implementing-practical-data-structures-in-kotlin-1st-edition-
raywenderlich-tutorial-team/
textboxfull.com

Data Structures Algorithms in Go 1st Edition Hemant Jain

https://textbookfull.com/product/data-structures-algorithms-in-go-1st-
edition-hemant-jain/

textboxfull.com

Codeless Data Structures and Algorithms: Learn DSA Without


Writing a Single Line of Code Armstrong Subero

https://textbookfull.com/product/codeless-data-structures-and-
algorithms-learn-dsa-without-writing-a-single-line-of-code-armstrong-
subero/
textboxfull.com

Algorithms and Data Structures in Action MEAP V12 Marcello


La Rocca

https://textbookfull.com/product/algorithms-and-data-structures-in-
action-meap-v12-marcello-la-rocca/

textboxfull.com
Learning Functional Data
Structures and Algorithms

Learn functional data structures and algorithms for


your applications and bring their benefits to your work
now

Atul S. Khot
Raju Kumar Mishra

BIRMINGHAM - MUMBAI
Learning Functional Data Structures and
Algorithms
Copyright © 2017 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or
transmitted in any form or by any means, without the prior written permission of the
publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the
information presented. However, the information contained in this book is sold without
warranty, either express or implied. Neither the authors, nor Packt Publishing, and its
dealers and distributors will be held liable for any damages caused or alleged to be caused
directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the
companies and products mentioned in this book by the appropriate use of capitals.
However, Packt Publishing cannot guarantee the accuracy of this information.

First published: February 2017

Production reference: 1170217

Published by Packt Publishing Ltd.

Livery Place

35 Livery Street

Birmingham B3 2PB, UK.

ISBN 978-1-78588-873-1
www.packtpub.com
Credits

Authors Copy Editor


Atul S. Khot Gladson Monteiro
Raju Kumar Mishra

Reviewer Project Coordinator


Muhammad Ali Ejaz Sheejal Shah

Commissioning Editor Proofreader


Kunal Parikh Safis Editing

Acquisition Editor Indexer


Denim Pinto Mariammal Chettiyar

Content Development Editor Graphics


Nikhil Borkar Abhinash Sahu

Technical Editor Production Coordinator


Hussain Kanchwala Shantanu Zagade
About the Authors
Atul S. Khot grew up in Marathwada, a region of the state of Maharashtra, India. A self-
taught programmer, he started writing software in C and C++. A Linux aficionado and a
command-line guy at heart, Atul has always been a polyglot programmer. Having
extensively programmed in Java and dabbled in multiple languages, these days, he is
increasingly getting hooked on Scala, Clojure, and Erlang. Atul is a frequent speaker at
software conferences, and a past Dr. Dobb's product award judge. In his spare time, he
loves to read classic British detective fiction. He is a foodie at heart and a pretty good cook.
Atul someday dreams of working as a master chef, serving people with lip-smacking
dishes.

He was the author of Scala Functional Programming Patterns published by Packt Publishing
in December 2015. The book looks at traditional object-oriented design patterns and shows
how we could use Scala's functional features instead.

I would like to thank my mother, late Sushila S. Khot, for teaching me the value of sharing.
Aai, I remember all you did for the needy girl students! Your support for the blind school -
you brought hope to so many lives! You are no more, however your kindness and selfless
spirit lives on! I know you are watching dear mother, and I will carry on the flame till I
live! I also would like to thank my father, late Shriniwas V. Khot. Anna, I have a photo of
the 'Tamra pat'--an engraved copper plaque--commemorating your great contribution to
the country's freedom struggle. You never compromised on core values --always stood for
the needy and poor. You live on in my memories--a hero forever! I would also want to
thank Martin Odersky for giving us the Scala programming language. I am deeply
thankful to Rich Hickey and the Clojure community for their work on persistent data
structures. Chris Okasaki’s "Purely Functional Data Structures" is a perennial source of
inspiration and insight. I wish to thank Chris for writing the book. This book is influenced
by many ideas Chris presented in his book. I also wish to thank the functional
programming community for all the technical writings which is a source of continual
learning and inspiration. I would love to express my heartfelt thanks to Nikhil Borkar for
all the support through out the book writing. I also would take this opportunity to thank
Hussain Kanchwala for the detailed editing efforts to make the book perfect. You guys are
awesome! Thanks to y’all!
Raju Kumar Mishra is a consultant and corporate trainer for big data and programming.
After completing his B.Tech from Indian Institute of Technology (ISM) Dhanbad, he worked
for Tata Steel. His deep passion for mathematics, data science, and programming took him
to Indian Institute of Science (IISc). After graduating from IISc in computational science, he
worked for Oracle as a performance engineer and software developer. He is an Oracle-
certified associate for Java 7. He is a Hortonworks-certified Apache Hadoop Java
developer, and holds a Developer Certification for Apache Spark (O'Reilly School of
Technology and Databriks), and Revolution R Enterprise-certified Specialist Certifications.
Apart from this, he has also cleared Financial Risk Manager (FRM I) exam. His interest in
mathematics helped him in clearing the CT3 (Actuarial Science) exam.

My heartiest thanks to the Almighty. I would like to thank my mom, Smt. Savitri Mishra,
my sisters, Mitan and Priya, and my maternal uncle, Shyam Bihari Pandey, for their
support and encouragement. I am grateful to Anurag Pal Sehgal, Saurabh Gupta, and all
my friends. Last but not least, thanks to Nikhil Borkar, Content Development Editor at
Packt Publishing for his support in writing this book.
About the Reviewer
Muhammad Ali Ejaz is currently pursuing his graduate degree at Stony Brook University.
His experience, leading up to this academic achievement, ranges from working as a
developer to cofounding a start-up, from serving in outreach organizations to giving talks
at various prestigious conferences. While working as a developer at ThoughtWorks, Ali
cofounded a career empowerment based start-up by providing photographers a platform to
showcase their art and be discovered by potential employers. His passion for computer
science is reflected in his contributions to open source projects, such as GoCD, and his role
in serving as the cofounder and Community Outreach Director of a non-profit organization,
"Women Who Code - Bangalore Chapter". Along with this, he has also been given the
opportunity to speak at different conferences on Continuous Integration and Delivery
practices.

When he is not coding, he enjoys traveling, reading, and tasting new cuisine. You can
follow him on Twitter at @mdaliejaz.

I want to thank my Mom and Dad, who have always been my inspiration. I’d also like to
thank Ahmad and Sana, my siblings, who have been a constant source of cheerful support.
A lot of what I am today is because of them.
www.PacktPub.com
For support files and downloads related to your book, please visit www.PacktPub.com.

Did you know that Packt offers eBook versions of every book published, with PDF and
ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a
print book customer, you are entitled to a discount on the eBook copy. Get in touch with us
at [email protected] for more details.

At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a
range of free newsletters and receive exclusive discounts and offers on Packt books and
eBooks.

https://www.packtpub.com/mapt

Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt
books and video courses, as well as industry-leading tools to help you plan your personal
development and advance your career.

Why subscribe?
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Customer Feedback
Thank you for purchasing this Packt book. We take our commitment to improving our
content and products to meet your needs seriously—that's why your feedback is so
valuable. Whatever your feelings about your purchase, please consider leaving a review on
this book's Amazon page. Not only will this help us, more importantly it will also help
others in the community to make an informed decision about the resources that they invest
in to learn. You can also review for us on a regular basis by joining our reviewers' club. If
you're interested in joining, or would like to learn more about the benefits we offer,
please contact us: [email protected].
Table of Contents
Preface 1
Chapter 1: Why Functional Programming? 8
The imperative way 9
Higher level of abstraction 10
Functional programming is declarative 13
No boilerplate 14
Higher order functions 16
Eschewing null checks 17
Controlling state changes 19
Recursion aids immutability 21
Copy-on-write 23
Laziness and deferred execution 24
Composing functions 26
Summary 29
Chapter 2: Building Blocks 30
The Big O notation 30
Space/time trade-off 33
A word frequency counter 34
Matching string subsets 36
Referential transparency 40
Vectors versus lists 42
Updating an element 46
Not enough nodes 47
Complexities and collections 48
The sliding window 48
Maps 49
Persistent stacks 51
Persistent FIFO queues 52
Sets 53
Sorted set 54
Summary 55
Chapter 3: Lists 56
First steps 57
List head and tail 61
Drop elements 64
Concatenating lists 66
Persistent data structures 69
Tail call optimization 70
List append 72
List prepend 74
Getting value at index 76
Modifying a list value 78
Summary 80
Chapter 4: Binary Trees 81
Node definitions 82
Building the tree 84
Size and depth 86
Complete binary trees 88
Comparing trees 89
Flipping a binary tree 91
Binary tree traversal 93
The accumulator idiom 95
Binary Search Trees 98
Node insertion 99
Searching a key 101
Updating a value 101
Exercising it 102
Summary 103
Chapter 5: More List Algorithms 104
Binary numbers 104
Addition 107
Multiplication 110
Greedy algorithms and backtracking 113
An example of a greedy algorithm 115
The backtracking jig 116
Summary 119
Chapter 6: Graph Algorithms 120
Reversing a list 121
Graph algorithms 123
Graph traversal 124
Avoiding list appending 128

[ ii ]
Topological sorting 129
Cycle detection 132
Printing the cycle 133
Summary 134
Chapter 7: Random Access Lists 136
Incrementing a binary number 137
Adding two binary numbers 139
List of tree roots 140
Insertion 142
Lookup 145
Removal, head, and tail 148
Update 151
Summary 152
Chapter 8: Queues 154
Understanding FIFO queues 155
Functional FIFO queues 156
Invariants 158
Implementing a priority queue 159
Understanding priority queues/heaps 161
Leftist trees 164
Functional heaps 166
Summary 173
Chapter 9: Streams, Laziness, and Algorithms 175
Program evaluation 176
Eager evaluation 176
Argument evaluation 178
Lazy evaluation 179
Lazy evaluation in Scala 180
Lazy evaluation in Clojure 182
Memoization – remembering past results 186
Memoization in Scala 188
Memoization in Clojure 190
Memoizing simpleFactFun 191
Streams 192
Stream in Scala 192
Indexing the elements of a stream 193
Creation of an infinite length stream 193
Stream is immutable 195
Creating a stream from another 196

[ iii ]
Stream to list 197
Appending one stream to another 198
Length of a stream 198
Some mathematical functions of the stream class 198
Some more methods of the stream class 199
Streams (lazy sequence) in Clojure 199
Creating a memoized function of lazy sequences in Clojure 200
Some algorithms on stream 200
Arithmetic progression 201
Arithmetic progression in Scala 202
Arithmetic progression in Clojure 202
Standard Brownian motion 203
Standard Brownian motion in Scala 203
Standard Brownian motion in Clojure 204
Fibonacci series 205
First form of Fibonacci series 205
Second form of Fibonacci series 205
Fibonacci series in Scala 206
Fibonacci series in Clojure 207
Summary 208
Chapter 10: Being Lazy - Queues and Deques 209
Imperative implementations 211
Amortization 212
Problem with queues 213
Strict versus lazy 214
Streams 215
Streams meet queues 217
A sense of balance 220
Amortized deques 221
Summary 225
Chapter 11: Red-Black Trees 227
Terminology 228
Almost balanced trees 229
The concept of rotation 229
Red-Black trees 231
Inserting a node 234
The Black-Red-Red path 237
Left, left – red child and grand child 238
Left child, right grand child 240
Right child, right grand child 241

[ iv ]
Right, left 242
Verifying the transformation 244
Complexity 245
Summary 246
Chapter 12: Binomial Heaps 247
Binomial trees 249
Left child, right sibling 252
A binomial heap 253
Linking up 254
Inserting a value 256
Binary number equivalence 259
Merging 260
Find the minimum 261
Deleting the minimum 262
Exercising the code 263
Complexity 264
Summary 265
Chapter 13: Sorting 266
Stable and unstable sorting 267
Stable sorting 268
Unstable sorting 268
Bubble sort 269
Scala implementation of bubble sort 272
Complexity of bubble sort 274
Selection sort 274
Complexity of selection sort 278
Insertion sort 278
Complexity of insertion sort 282
Merge sort 282
Splitting the sequence 283
Merging two sorted subsequences 285
Complexity of merge sort 289
Quick sort 289
Partition 290
Complexity of quick sort 293
Summary 293
Index 294

[v]
Preface
This book is about functional algorithms and data structures. Algorithms and data
structures are fundamentals of computer programming.

I started my career writing C and C++ code. I always enjoyed designing efficient algorithms.
I have experienced many an Aha! moments, when I saw how powerful and creative pointer
twiddling could be!

For example, reversing a singly linked list using three node pointers is a well known
algorithm. We scan the list once and reverse it by changing the pointer fields of each node.
The three pointer variables guide the reversal process.

I have come across many such pointer tricks and have used them as needed.

I was next initiated into the world of multi-threading! Variables became shared states
between threads! My bagful of tricks was still valid; however, changing state needed a lot of
care, to stay away from insidious threading bugs.

The real world is never picture perfect and someone forgot to synchronize a data structure.

Thankfully we started using C++, which had another bagful of tricks, to control the state
sharing. You could now make objects immutable!

For example, we were able to implement the readers/writer locking pattern effectively.
Immutable objects could be shared without worry among thousands of readers!

We slept easier, the code worked as expected, and all was well with the world!

I soon realized the reason it worked well! Immutability was finally helping us better
understand the state changes!
Preface

The sands of time kept moving and I discovered functional programming.

I could very well see why writing side-effect free code worked! I was hooked and started
playing with Scala, Clojure, and Erlang. Immutability was the norm here.

However, I wondered how the traditional algorithms would look like in a functional
setting--and started learning about it.

A data structure is never mutated in place. Instead, a new version of the data structure is
created. The strategy of copy on write with maximized sharing was an intriguing one! All
that careful synchronization is simply not needed!

The languages come equipped with garbage collection. So, if a version is not needed
anymore, the runtime would take care of reclaiming the memory.

All in good time though! Reading this book will help you see that we need not sacrifice
algorithmic performance while avoiding in-place mutation!

What this book covers


Chapter 1, Why Functional Programming?, takes you on a whirlwind tour of the functional
programming (FP) paradigm. We try to highlight the many advantages FP brings to the
table when compared with the imperative programming paradigm. We discuss FP’s higher
level of abstraction, being declarative, and reduced boilerplate. We talk about the problem
of reasoning about the state change. We see how being immutable helps realize "an easier to
reason about system".

Chapter 2, Building Blocks, provides a whirlwind tour of basic concepts in algorithms. We


talk about the Big O notation for measuring algorithm efficiency. We discuss the space time
trade-off apparent in many algorithms. We next look at referential transparency, a
functional programming concept. We will also introduce you to the notion of persistent
data structures.

Chapter 3, Lists, looks at how lists are implemented in a functional setting. We discuss the
concept of persistent data structures in depth here, showing how efficient functional
algorithms try to minimize copying and maximize structural sharing.

Chapter 4, Binary Trees, discusses binary trees. We look at the traditional binary tree
algorithms, and then look at Binary Search Trees.

[2]
Preface

Chapter 5, More List Algorithms, shows how the prepend operation of lists is at the heart of
many algorithms. Using lists to represent binary numbers helps us see what lists are good
at. We also look at greedy and backtracking algorithms, with lists at the heart.

Chapter 6, Graph Algorithms, looks at some common graph algorithms. We look at graph
traversal and topological sorting, an important algorithm for ordering dependencies.

Chapter 7, Random Access Lists, looks at how we could exploit Binary Search Trees to access
a random list element faster.

Chapter 8, Queues, looks at First In First Out (FIFO) queues. This is another fundamental
data structure. We look at some innovative uses of lists to implement queues.

Chapter 9, Streams, Laziness, and Algorithms, looks at lazy evaluation, another FP feature.
This is an important building block for upcoming algorithms, so we refresh ourselves with
some deferred evaluation concepts.

Chapter 10, Being Lazy – Queues and Deques, looks at double-ended queues, which allow
insertion and deletion at both ends. We first look at the concept of amortization. We use
lazy lists to improve the queue implementation presented earlier, in amortized constant
time. We implement deques also using similar techniques.

Chapter 11, Red-Black Trees, shows how balancing helps avoid degenerate Binary Search
Trees. This is a comparatively complex data structure, so we discuss each algorithm in
detail.

Chapter 12, Binomial Heaps, covers heap implementation offering very efficient merge
operation. We implement this data structure in a functional setting.

Chapter 13, Sorting, talks about typical functional sorting algorithms.

What you need for this book


You need to install Scala and Clojure. All the examples were tested with Scala version
2.11.7. The Clojure examples were tested with Clojure version 1.6.0. You don’t need any
IDE as most of the examples are small enough, so you can key them in the REPL
(Read/Eval/Print Loop).

You also need a text editor. Use whichever you are comfortable with.

[3]
Preface

Who this book is for


The book assumes some familiarity with basic data structures. You should have played
with fundamental data structures like linked lists, heaps, and binary trees. It also assumes
that you have written some code in a functional language.

Scala is used as an implementation language. We do highlight related Clojure features too.


The idea is to illustrate the basic design principles.

We explain the language concepts as needed. However, we just explain the basics and give
helpful pointers, so you can learn more by reading the reference links.

We try to site links that offer hands-on code snippets, so you can practice them yourself.

Walking through an algorithm and discussing the implementation line by line is an


effective aid to understanding.

A lot of thought has gone into making helpful diagrams. Quizzes and exercises are
included, so you can apply what you've learned.

All the code is available online. We strongly advocate keying in the code snippets though,
to internalize the principles and techniques.

Welcome to the wonderland of functional data structures and algorithms!

Conventions
In this book, you will find a number of text styles that distinguish between different kinds
of information. Here are some examples of these styles and an explanation of their meaning.

Code words in text, database table names, folder names, filenames, file extensions,
pathnames, dummy URLs, user input, and Twitter handles are shown as follows: "The
following function f has a side effect, though."

A block of code is set as follows:


user=> (def v [7 11 19 52 42 72])
#'user/v
user=> (def v1 (conj v 52))
#'user/v1

[4]
Preface

If there is a line (or lines) of code that needs to be highlighted, it is set as follows:
scala> def pop(queue: Fifo): (Int, Fifo) = {
| queue.out match {
| case Nil => throw new IllegalArgumentException("Empty queue");
| case x :: Nil => (x, queue.copy(out = queue.in.reverse, Nil))
| case y :: ys => (y, queue.copy(out = ys))
| }
| }
pop: (queue: Fifo)(Int, Fifo)

New terms and important words are shown in bold. Words that you see on the screen, for
example, in menus or dialog boxes, appear in the text like this: "Clicking the Next button
moves you to the next screen."

Warnings or important notes appear in a box like this.

Tips and tricks appear like this.

Reader feedback
Feedback from our readers is always welcome. Let us know what you think about this
book—what you liked or disliked. Reader feedback is important for us as it helps us
develop titles that you will really get the most out of.

To send us general feedback, simply e-mail [email protected], and mention the


book's title in the subject of your message.

If there is a topic that you have expertise in and you are interested in either writing or
contributing to a book, see our author guide at www.packtpub.com/authors.

Customer support
Now that you are the proud owner of a Packt book, we have a number of things to help you
to get the most from your purchase.

[5]
Preface

Downloading the example code


You can download the example code files for this book from your account at http://www.p
acktpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.c
om/supportand register to have the files e-mailed directly to you.

You can download the code files by following these steps:

1. Log in or register to our website using your e-mail address and password.
2. Hover the mouse pointer on the SUPPORT tab at the top.
3. Click on Code Downloads & Errata.
4. Enter the name of the book in the Search box.
5. Select the book for which you're looking to download the code files.
6. Choose from the drop-down menu where you purchased this book from.
7. Click on Code Download.

Once the file is downloaded, please make sure that you unzip or extract the folder using the
latest version of:

WinRAR / 7-Zip for Windows


Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux

The code bundle for the book is also hosted on GitHub at https://github.com/PacktPubl
ishing/Learning-Functional-Data-Structures-and-Algorithms. We also have other
code bundles from our rich catalog of books and videos available at https://github.com/P
acktPublishing/. Check them out!

Downloading the color images of this book


We also provide you with a PDF file that has color images of the screenshots/diagrams used
in this book. The color images will help you better understand the changes in the output.
You can download this file from https://www.packtpub.com/sites/default/files/down
loads/LearningFunctionDataStructuresandAlgorithms_ColorImages.pdf.

[6]
Preface

Errata
Although we have taken every care to ensure the accuracy of our content, mistakes do
happen. If you find a mistake in one of our books—maybe a mistake in the text or the
code—we would be grateful if you could report this to us. By doing so, you can save other
readers from frustration and help us improve subsequent versions of this book. If you find
any errata, please report them by visiting http://www.packtpub.com/submit-errata,
selecting your book, clicking on the Errata Submission Form link, and entering the details
of your errata. Once your errata are verified, your submission will be accepted and the
errata will be uploaded to our website or added to any list of existing errata under the
Errata section of that title.

To view the previously submitted errata, go to https://www.packtpub.com/books/conten


t/supportand enter the name of the book in the search field. The required information will
appear under the Errata section.

Piracy
Piracy of copyrighted material on the Internet is an ongoing problem across all media. At
Packt, we take the protection of our copyright and licenses very seriously. If you come
across any illegal copies of our works in any form on the Internet, please provide us with
the location address or website name immediately so that we can pursue a remedy.

Please contact us at [email protected] with a link to the suspected pirated material.

We appreciate your help in protecting our authors and our ability to bring you valuable
content.

Questions
If you have a problem with any aspect of this book, you can contact us at
[email protected], and we will do our best to address the problem.

[7]
Why Functional Programming?
1
What is functional programming (FP)? Why is it talked about so much?

A programming paradigm is a style of programming. FP is a programming paradigm


characterized by the absence of side effects.

In FP, functions are the primary means of structuring code. The FP paradigm advocates
using pure functions and stresses on immutable data structures. So we don't mutate variables,
but pass a state to function parameters. Functional languages give us lazy evaluation and
use recursion instead of explicit loops. Functions are first-class citizens like numbers or
strings. We pass functions as argument values, just like a numeric or string argument. This
ability to pass functions as arguments allows us to compose behavior, that is, cobble
together something entirely new from existing functions.

In this chapter, we will take a whirlwind tour of functional programming. We will look at
bits of code and images to understand the concepts. This will also lay a nice foundation for
the rest of the book. We will use the functional paradigm and see how it changes the way
we think about data structures and algorithms.

This chapter starts with a look at the concept of abstraction. We will see why abstractions
are important in programming. FP is a declarative style of programming, similar to
Structured Query Language (SQL). Because it is declarative, we use it to tell what we want
the computer to do, rather how it should do it. We will also see how this style helps us stay
away from writing common, repetitive boilerplate code.
Why Functional Programming?

Passing functions as arguments to other, higher order functions is the central idea in FP; we
look at this next. We will also see how to stay away from null checks. Controlled state
change allows us to better reason our code. Being immutable is the key for creating code
that would be easier to reason about.

Next, we will see how recursion helps us realize looping without mutating any variables.
We will wrap up the chapter with a look at lazy evaluation, copy-on-write, and functional
composition.

The imperative way


We keep contrasting FP with the imperative style of programming. What do we mean by
imperative style, though?

The imperative programming style is embodied by a sequence of commands modifying a


program's state. A simple example of this is a for loop. Consider the following pseudo code
snippet to print all the elements of an array:
x = [1,2,3,4...] // an array, x.size tells the number of array elements
for( int i = 0; i < x.size; ++i ) {
println(x[i])
}

Here is a pictorial rendering of the concepts:

[9]
Why Functional Programming?

As the figure shows, the for loop establishes an initial state by setting the variable i to 0.
The variable is incremented every time the loop is repeated; this is what we mean by the
state being modified. We keep reading and modifying the state, that is, the loop variable,
until there are no elements left in the array.

FP advocates staying away from any state modification. It gives us tools so we don't worry
about how to loop over a collection; instead, we focus on what we need to do with each
element of the collection.

Higher level of abstraction


FP allows us to work at a higher level of abstraction. Abstraction is selective ignorance. The
world we know of runs on abstractions. If we say, “Give me sweet condensed milk frozen
with embedded dry fruits' someone might really have a hard time understanding it.
Instead, just say “ice-cream”! Aha! It just falls into place and everyone is happy.

Abstractions are everywhere. An airplane is an abstraction, so is a sewing machine or a


train. When we wish to travel by train, we buy a ticket, board the train, and get off at the
destination. We really don't worry about how the train functions. We simply can't be
expected to deal with all the intricacies of a train engine. As long as it serves our purpose,
we ignore details related to how an engine really works.

What are the benefits of an abstraction? We don't get bogged down into unnecessary
details. Instead, we focus on the task at hand by applying higher level programming
abstractions.

Compare the preceding for loop with the functional code snippet:
scala> val x = Array(1,2,3,4,5,6)
x: Array[Int] = Array(1, 2, 3, 4, 5, 6)
scala> x.foreach(println _)
1
2
...

We simply focus on the task at hand (print each element of an array) and don't care about
the mechanics of a for loop. The functional version is more abstract.

[ 10 ]
Why Functional Programming?

As software engineers, when we implement an algorithm and run it, we are intentionally
ignoring many details.

We know that the preceding sandwich stack somehow works and faithfully translates the
algorithm into runnable code.

Applying higher level abstractions is commonly done in functional languages. For example,
consider the following Clojure REPL snippet:
user=> ((juxt (comp str *) (comp str +)) 1 2 3 4 5)
["120" "15"]

[ 11 ]
Why Functional Programming?

We are juxtaposing two functions; each of these are in turn composed of the str function
and an arithmetic function:

We just don't worry about how it works internally. We just use high-level abstractions
cobbled together with existing pieces of abstract functionality.

We will be looking at abstract data types (ADT) closely in this book. For example, when we
talk about a stack, we think of the Last In First Out (LIFO) order of access. However, this
ADT is realized by implementing the stack via a data structure, such as a linked list or an
array.

[ 12 ]
Why Functional Programming?

Here is a figure showing the First In First Out (FIFO) ADT in action. The FIFO queue is the
normal queue we encounter in life, for example, queuing up at a booking counter. The
earlier you get into a queue, the sooner you get serviced.

The FIFO queue is an ADT. True that we think of it as an ADT; however, as shown in the
preceding diagram, we can also implement the queue backed by either an array or a linked
list.

Functional programming is declarative


When we use SQL, we just express our intent. For example, consider this:
mysql> select count(*) from book where author like '%wodehouse%';

We just say what we are looking for. The actual mechanism that gets the answer is hidden
from us. The following is a little too simplistic but suitable example to prove the point.

[ 13 ]
Why Functional Programming?

The SQL engine will have to loop over the table and check whether the author column
contains the wodehouse string. We really don't need to worry about the search algorithm.
The author table resides on a disk somewhere. The number of table rows that need to be
filtered could easily exceed the available memory. The engine handles all such complexities
for us though.

We just declare our intent. The following Scala snippet is declarative. It counts the number of
even elements in the input list:
scala> val list = List(1, 2, 3, 4, 5, 6)
list: List[Int] = List(1, 2, 3, 4, 5, 6)

scala> list.count( _ % 2 == 0 )
res0: Int = 3

The code uses a higher order function, namely count. This takes another function, a
predicate, as an argument. The line loops over each list element, invokes the argument
predicate function, and returns the count.

Here is another example of Clojure code that shows how to generate a combination of
values from two lists:
user=> (defn fun1 [list1 list2]
#_=> (for [x list1 y list2]
#_=> (list x y)))
#'user/fun1
user=> (fun1 '(1 2 3) '(4 5 6))
((1 4) (1 5) (1 6) (2 4) (2 5) (2 6) (3 4) (3 5) (3 6))

Note the code used to generate the combination. We use for comprehension to just state what
we need done and it would be done for us.

No boilerplate
Boilerplate code consists sections of the same code written again and again. For example,
writing loops is boilerplate, as is writing getters and setters for private class members.

[ 14 ]
Why Functional Programming?

As the preceding code shows, the loop is implicit:


scala> List(1, 2, 3, 4, 5) partition(_ % 2 == 0)
res3: (List[Int], List[Int]) = (List(2, 4),List(1, 3, 5))

We just wish to separate the odd and even numbers. So we just specify the criteria via a
function, an anonymous function in this case. This is shown in the following image:

What is boilerplate? It is a for loop, for example. In the imperative world, we code the loop
ourselves. We need to tell the system how to iterate over a data structure.

Isn't Scala code just to the point? We tell what we need and the loop is implied for us. No
need to write a for loop, no need to invent a name for the loop variable, and so on. We just
got rid of the boilerplate.

Here is a Clojure snippet that shows how to multiply each element of a vector by 2:
user=> (map * (repeat 2) [1 2 3 4 5])
(2 4 6 8 10)

The map function hides the loop from us. Then (repeat 2) function call generates an
infinite sequence.

[ 15 ]
Exploring the Variety of Random
Documents with Different Content
beweisen. Die genaue Festlegung seiner südlichsten
Verbreitungsgrenze, die zu ziehen uns heute in Ermangelung der
notwendigen Unterlagen noch nicht möglich ist, wäre
tiergeographisch aber von großem Werte. – Die Unterscheidung von
unserem Grasfrosche, dem er äußerlich so auffallend ähnelt, daß er
als eigene Art erst in verhältnismäßig später Zeit erkannt worden ist,
und dann auch lange noch ein Streitobjekt gebildet hat, wird den
Anfänger allerdings noch einige Schwierigkeiten bereiten, ihm mit
Sicherheit aber möglich sein, sobald er beide Arten einmal
gleichzeitig nebeneinander gehabt hat und miteinander hat
vergleichen können. Der Moorfrosch unterscheidet sich vom
Grasfrosch durch die etwas schmalere Stirn und die spitzer
auslaufende Schnauze, durch den stets ungefleckten Bauch (beim
Grasfrosch ist er fast immer dunkel gefleckt) und untrüglich durch
den sogenannten Fersenhöcker, eine längliche, schwielenartige
Erhebung an der Wurzel der inneren Zehe der Hinterfüße, der allen
Fröschen eigen ist und ein sicheres Artmerkmal bildet. Beim
Moorfrosch ist er stark und hart, schaufelartig seitlich
zusammengedrückt und immer länger als die halbe Innenzehe, beim
Grasfrosch dagegen ist er schwach und weich und bildet einen
länglich-stumpfen Wulst von jederzeit geringerer Länge als die Hälfte
der Innenzehe.
Abb. 3 Kletternde Ringelnatter

Ähnlich wie beim Moorfrosch ist die genaue Festlegung der


Südgrenze des Vorkommens auch von der Grünen und der
Kreuzkröte vonnöten. Die Grüne Kröte ist eine häufige Erscheinung
in der gesamten Leipziger Tieflandsbucht, aus der sie zum
mindesten auch bis ins sächsische Mittelgebirge aufsteigt; ich
konnte sie bei Göppersdorf bei Burgstädt als an den bisher
bekannten südlichsten Fundort nachweisen. Dann tritt sie wieder
zahlreich im Flußgebiet der Elbe auf, in dem sie in der ganzen
weiten Umgebung Dresdens vorkommt und stromaufwärts bis über
Pirna hinauf ihr Vorkommen ausdehnt. Aus dem Osten unseres
Landes waren Vorkommen unserer Art im Schrifttum bisher zwar
noch nicht festgelegt, doch fehlt sie ihm keineswegs, sondern
verbreitet sich von der Elbe aus in östlicher Richtung, zum
mindesten über das gesamte Oberlausitzer Teichgebiet, in dem ich
sie in den letzten Jahren wiederholt als durchaus nicht selten
feststellen konnte. Aus dem Gebiete zwischen Mulde und Elbe ist sie
bisher noch nicht nachgewiesen worden, wahrscheinlich, weil dieses
bisher so herzlich wenig ihre Beobachtungen auch bekannt gebende
Naturbeobachter aufzuweisen gehabt hat. Die Kreuzkröte kommt
zunächst in der unmittelbarsten Umgebung Leipzigs vor, scheint sich
aber von hier aus nicht wie die Grüne Kröte weiter südwärts zu
verbreiten – mir wenigstens glückte bisher trotz jahrelanger
Nachforschungen der Nachweis ihres Vorkommens hier noch
nicht –, wird aber dann wieder, durch ein räumlich recht großes
Gebiet vom Leipziger Vorkommen getrennt, von Chemnitz erwähnt
und konnte von mir im Sommer 1919 in großer Zahl auch bei
Limbach festgestellt werden. Das Chemnitz-Limbacher Vorkommen
scheint ein völlig in sich Geschlossenes, inselartiges zu bilden. Dann
ist sie auch, wiederum durch das Gebiet zwischen Mulde und Elbe
von den westsächsischen Vorkommen getrennt, in der Umgebung
Dresdens nachgewiesen. Aus der Lausitz war sie bisher nicht
bekannt, dürfte aber wohl auch hier noch an manchem Ort
nachzuweisen sein, nachdem ich sie im Sommer 1924 bei
Königswartha aufgefunden habe.
Abb. 4 Vor ihrem Schlupfwinkel sich sonnende Glatte Natter

Die drei Kröten sind äußerlich recht gut voneinander


unterschieden und ihre sichere Bestimmung dürfte selbst dem
Ungeübten keine großen Schwierigkeiten bereiten. Die Erdkröte, die
verbreitetste und wohl überall gleich häufige der Sippe, ist von
graubrauner, bald ins asch- und schwärzlichgraue, bald wieder ins
gelblich- und oliven-graue und -bräunliche übergehender Farbe, die
sich allmählich in den helleren Ton der Unterseite auflöst; die Grüne
Kröte ist auf hellerem ledergelben bis gelbgrauen Grunde ziemlich
dicht mit satten samt- bis grasgrünen Flecken gezeichnet, von denen
sich besonders an den Seiten und am Halse zahlreiche rote
Wärzchen abheben, während die unterseits ebenfalls wieder in
hellere Töne übergehende Farbe der Kreuzkröte ein bald mehr ins
gelbliche oder graue, bald wieder ins braune übergehendes Oliv ist,
durch das längs der Rückenmitte ein etwas vertiefter, schwefelgelber
Streifen verläuft.
Abb. 5 An einem senkrechten Baumstamm emporkletternde
Glatte Natter
Abb. 6 Zauneidechse, Angriffsstellung

Eine ähnliche Verbreitung wie der Moorfrosch und die Grüne Kröte
besitzt in Sachsen auch die froschähnliche (und der Familie der
Froschkröten angehörende) Knoblauchskröte, die erheblich kleiner
als die eben betrachteten Vertreter der echten Kröten ist, und der
auch die für diese so bezeichnende warzige Hautoberfläche abgeht.
Ihre Farbe ist ein helleres oder dunkleres Grau oder Braun, das mit
kastanienbraunen bis schwärzlichen Flecken und allerlei roten
Punkten und Tüpfelchen gezeichnet ist. Als ein Tier des Tieflandes
verbreitet sie sich zunächst wiederum über die gesamte Leipziger
Tieflandsbucht und steigt aus dieser dann auch ins Hügelland und
ins Mittelgebirge empor, wo sie bei Lunzenau nachgewiesen werden
konnte. Dann kommt sie gleichfalls wieder im Flußgebiet der Elbe
vor und scheint sich hier stromaufwärts ähnlich wie die Grüne Kröte
bis Pirna hinauf, und in östlicher Richtung über das Oberlausitzer
Tieflandsgebiet zu verbreiten. – Nicht so weit südwärts wie die eben
genannten Arten scheint sich dagegen die Rotbauchunke zu
verbreiten, die auch innerhalb ihres durch das nordsächsische
Tiefland gekennzeichneten Vorkommens sehr lückenhaft verbreitet
zu sein scheint.

Abb. 7 Berg- oder Waldeidechse


Abb. 8 Blindschleiche
Abb. 9 Wasserfrosch

Waren die bisher betrachteten Arten Tieflandsbewohner, deren


genaue Verbreitungsgrenze vor allem gebirgswärts noch festzulegen
ist, so besitzen wir im Feuersalamander und im Bergmolch zwei
Lurche, die Bewohner des Berg- und Hügellandes sind und von
denen neben ihrer genauen Verbreitung innerhalb desselben vor
allem noch die unteren Verbreitungsgrenzen festzulegen sind. Der
Feuersalamander erreicht in Westsachsen auf dem Rochlitzer Berge
die Nordgrenze seiner Verbreitung und dehnt von hier aus sein
Vorkommen nur im Muldentale noch bis in die Colditzer und
Grimmaer Gegend aus, während ich ihn im Zschopautale am
weitesten nördlich bei Waldheim gefunden habe. Die Grenzen des
Vorkommens des Bergmolches dagegen liegen noch nördlicher, ich
begegnete ihm noch bei Geithain und im Muldental ebenfalls bis in
die Gegend von Grimma, von wo aus er sich dann noch bis in die
Pflege von Beucha-Brandis verbreitet. Im Gebiete der Elbe scheint
das Vorkommen des Feuersalamanders kurz vor Meißen
auszuklingen, der Bergmolch aber auch hier noch weiter ins Tiefland
vorzudringen. –

Abb. 10 Grasfrosch
Abb. 11 Laubfrosch
Von den vier Schlangen Sachsens ist die Ringelnatter die
häufigste und eine über das ganze Land verbreitete Art; es dürfte bei
uns kaum ein größeres Gebiet geben, dem sie fehlt. Ihre größte
Häufigkeit erreicht sie in den teich- und wasserreichen Landschaften
des Flachlandes, wo sie, wie z. B. an vielen Teichen der
Oberlausitzer Niederung in manches Mal fast unglaublichen Mengen
sich findet. – Groß (und jedenfalls bei weitem größer, als so mancher
meint) ist auch das Verbreitungsgebiet der Kreuzotter, die aus den
gebirgigen Teilen des Landes – Vogtland und Erzgebirge
beherbergen sie in besonders großer Zahl – bis weit ins
nordsächsische Flachland hinein und darüber hinaus vordringt. Als
kreuzotterfrei gilt nur der äußerste von der Elsteraue eingenommene
Nordwesten des Landes sowie ein Gebiet, das rechts der
Vereinigten Mulde beginnt, im Süden auf die Freiberger Mulde trifft
und sich bis nördlich Freiberg ausbuchtet, dann südlich Meißen die
Elbe kreuzt und östlich Großenhain im Norden auf die Landesgrenze
stößt. Gebildet wird es von Teilen der Amtshauptmannschaften
Oschatz, Döbeln, Meißen und Großenhain. Kreuzotterfrei scheint
endlich noch der äußerste Osten der Lausitz, etwa aus der Gegend
von Bautzen an bis zu den Vorbergen des Zittauer Gebirges zu sein,
während die nördlichen Teichgebiete – ich konnte erst im
vergangenen Frühjahr wieder eine Anzahl diesbezüglicher
Feststellungen machen – die Schlange überall noch beherbergen
und durchaus nicht als »Storch«gebiete kreuzotterfrei sind.
Abb. 12 Knoblauchskröte (sich eingrabend)
Abb. 13 Rotbauchunke

In vielem mangelhaft dagegen sind wir noch über die Verbreitung


der Glatten Natter in Sachsen unterrichtet. Sie ist ebenfalls nicht
selten, scheint aber ein kleineres Verbreitungsgebiet als ihre
Verwandten zu besitzen. Sie steigt bei uns aus dem Flachland in das
Hügelland, in dem sie in Sachsen auch ihre größte Häufigkeit zu
erreichen scheint, und in die niederen und wärmeren Lagen der
Gebirge empor; sie ist ungleich wärmebedürftiger als die Kreuzotter
und scheint dazu allen höheren und rauheren Teilen völlig zu fehlen.
Abb. 14 Feuersalamander
Abb. 15 Teichmolch (Aquarienaufnahme)

* *
*

Bei diesen wenigen Hinweisen auf noch offene Fragen der


Kriechtier- und Lurchverbreitung in Sachsen soll es jedoch für heute
bleiben, obwohl ich sie leicht noch weiter ausdehnen könnte. Ihr
Anschneiden an dieser Stelle soll lediglich eine Anregung für die
Leser der »Mitteilungen« sein, nach Kräften an ihrer Lösung
mitzuarbeiten. Mitteilungen nimmt der Verfasser (Dresden, Marienstr.
32) jederzeit mit Dank entgegen; sie werden Verwendung finden in
der in Arbeit befindlichen »Sächsischen Wirbeltierfauna«, die ich
zusammen mit R. Heyder und R. Zaunick bearbeite.

Fußnoten:
[1] Siehe auch: Zimmermann, Rud., Ein Beitrag zur Lurch- und
Kriechtierfauna des ehemaligen Königreichs Sachsen. Archiv für
Naturgeschichte 88, 1922 A, 8. Heft, 245–267.
[2] Zimmermann, Rud., Das Vorkommen der Sumpfschildkröte im
Gebiet des ehemaligen Königreichs Sachsen. Fischerei-Zeitung
24, Neudamm 1921, 250–253.
Otto Altenkirch
Ein Maler der sächsischen Landschaft

Von Edgar Hahnewald


Der Heller flimmert in brandigem Dunst. Die Sandflächen breiten
ein fahles Gelbgrau über den Vordergrund, von dem sich einige
schmale Heidekrautinseln in trockenem Braunviolett mit vereinzelten
grünen Flecken darin abheben. Weiter hinten streckt sich eine
Windgrassteppe, weich wie Haar und kupfern in der Farbe, vor
einem Waldstreifen, dessen Kiefernwipfel einer schweren Wolke
gleich tief auf der Fläche zu liegen scheinen und nur am Rande, wo
der Wald sich lockert, von einzelnen Stämmen wie von Stützen über
der Erde gehalten werden. Über dem Walde steht hoch, prachtvoll,
in einem stumpfen, dunklen Stahlblau eine Gewitterwolke wie ein
riesenhaftes Haupt ohne Antlitz, von einer Aureole hervorbrechender
Lichter umstrahlt. Sie steht regungslos, als warte sie noch, ehe sie
mit rollender Donnerstimme in die Landschaft spricht. Unter diesem
Wolkenhaupt drängt sich das bißchen Landschaft noch enger an die
bleiche Erde. Nur eine Birke steht ganz allein mitten in der
Sandfläche auf einem kleinen zerrissenen Teppich von Heidekraut.
Ihr von vielen Stürmen verbogener Stamm, vor dem Stahlblau
unwahrscheinlich weiß, überschneidet den fernen Waldstreifen und
hält einen Laubbüschel wie eine zerfetzte Fahne hoch vor die
drohende Wand.
Und noch jemand steht in der spärlichen Fläche. Ein Maler vor
seiner Staffelei. Die Krempe eines in vielen Wettern verblichenen
Hutes beschattet seine Augen. Er trägt eine alte, mit allen Farben
seiner Palette beklexte Jacke und blank getretene Holzpantoffeln,
die ihm das stundenlange Stehen erleichtern. Er sieht in dieser
Kleidung einem Handwerker ähnlicher als einem Künstler. Ein Blick
auf seine Leinwand auf der Staffelei zeigt, daß er ein Künstler ist. Im
kleineren Abbild ist dort die Landschaft noch einmal, der Sand, das
Heidekraut, das Windgras, der Wald, die Birke, die Gewitterwand.
Das Bild läßt erkennen, was in dieser scheinbar kargen eintönigen
Sandebene den Maler reizte: das einsame Aufstehen der Birke über
dem ganz tiefgenommenen Horizont, ihr Hinaufweisen in die hohe
drohende Wolke, die vier Fünftel des Bildraumes beherrscht. Aber
nicht allein das, nicht nur die beinahe trotzige, beinahe tragische
Einsamkeit der Birke mit der zerschlissenen Laubfahne in der kargen
Landschaft macht diesen künstlerisch gesehenen Ausschnitt zum
Bilde. Das rein malerische des Motivs zog den Künstler an. Die
flimmernde, von sommerlichen Dünsten geschwängerte
Atmosphäre, das irrende Spiel fliehender Lichter am Himmel und
über den Farben des Sandes und der Heide, das beinahe
Geängstete, Erschreckte dieser Landschaft unter dem schweren
Dunkel der riesenhaften Wolke. Der eigenartige Gegensatz
zwischen dieser drohenden Erscheinung, die in ihrer stahlblauen
Ruhe und Ballung wie ein Dämon wirkt und doch schwere,
sommerliche Sättigung verheißt – der Gegensatz zwischen ihr und
der flimmernden Unrast, der Erregung in der kleinen Landschaft, die
bleich in zitternder Luft sich hinschmiegt, den ersten Donnerschlag
fürchtend und doch die Sättigung mit aller Glut des trockenen
Sandes erwartend – das ist in freilich literarischer Übertragung der
malerische Reiz dieser Landschaft, an der nach der Meinung des
Laien »aber auch gar nichts« ist. Einfach: Anreiz für den Maler ist
der unendliche Zauber des Lichts, und das landschaftliche Motiv ist
nur der Träger, an dem dieser Zauber sichtbar wird.
Der Maler ist stumm an sein Werk hingegeben. Aus dem
Hutschatten hervor prüfen die zusammengekniffenen Augen immer
wieder bald die Landschaft, bald das Bild. Unter der großen Palette
hervor sprießen bereit gehaltene Pinsel wie ein starrer Strauß. Der
Maler arbeitet mit dem Spachtel, diesem kleinen Werkzeug aus
federndem Stahl, an das hölzerne Heft angebogen wie eine Kelle
und schmal wie ein Brieföffner. Auf der Palette mischt der Spachtel
leise klingend die gebrauchte Farbe und mit einem Spachteldruck
verwandelt sich das Klexchen Farbenpaste auf der Leinwand in
einen Büschel violetter Heide, der wie eine lebendige Flamme im
bleichen Sande lodert.
Trüber Tag Dresdner Heller

Über den Heller kommen zwei Frauen mit Heidelbeerkrügen. Das


drohende Gewitter hat sie aus dem Walde vertrieben. Beim Maler
bleiben sie stehen. In seiner beklexten Jacke, in seinen
Holzpantoffeln halten sie ihn für ihresgleichen, für einen
erwerbslosen Malergesellen vielleicht, der auf diese Weise sich ein
paar Mark zu verdienen sucht. Sie halten darum mit ihrer Kritik auch
nicht hinterm Berge. Sie meinen, es gibt schönere Sachen, die man
malen könnte als da den Sand und die dumme Birke. Aber die
Wolke mit dem dahinter hervorbrechenden Licht findet ihre
Anerkennung. Und wie lange er an einem solchen Bilde male? So –
im Varieté hat die eine Frau einmal einen Schnellmaler gesehen, der
malte in fünf Minuten ein Bild, größer als das hier, mit einem Fluß
und Bergen, Schiffen und einer Windmühle. Und gleich so mit dem
Pinsel los. Der konnte was!
Der Maler antwortet auf die naiven Fragen der Frauen, ohne sich
lustig zu machen. Er ist innerlich dem einfachen Volke
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

textbookfull.com

You might also like