100% found this document useful (3 votes)
31 views

Domain Specific Languages in R Advanced Statistical Programming 1st Edition Thomas Mailund 2024 scribd download

Programming

Uploaded by

khathboornri
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (3 votes)
31 views

Domain Specific Languages in R Advanced Statistical Programming 1st Edition Thomas Mailund 2024 scribd download

Programming

Uploaded by

khathboornri
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 55

Download the Full Version of textbook for Fast Typing at textbookfull.

com

Domain Specific Languages in R Advanced


Statistical Programming 1st Edition Thomas Mailund

https://textbookfull.com/product/domain-specific-languages-
in-r-advanced-statistical-programming-1st-edition-thomas-
mailund-2/

OR CLICK BUTTON

DOWNLOAD NOW

Download More textbook Instantly Today - Get Yours Now at textbookfull.com


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

Domain Specific Languages in R Advanced Statistical


Programming 1st Edition Thomas Mailund

https://textbookfull.com/product/domain-specific-languages-in-r-
advanced-statistical-programming-1st-edition-thomas-mailund-2/

textboxfull.com

Functional Data Structures in R: Advanced Statistical


Programming in R Thomas Mailund

https://textbookfull.com/product/functional-data-structures-in-r-
advanced-statistical-programming-in-r-thomas-mailund/

textboxfull.com

Functional Data Structures in R: Advanced Statistical


Programming in R Mailund

https://textbookfull.com/product/functional-data-structures-in-r-
advanced-statistical-programming-in-r-mailund/

textboxfull.com

Functional Programming in R: Advanced Statistical


Programming for Data Science, Analysis and Finance 1st
Edition Thomas Mailund
https://textbookfull.com/product/functional-programming-in-r-advanced-
statistical-programming-for-data-science-analysis-and-finance-1st-
edition-thomas-mailund/
textboxfull.com
Metaprogramming in R: Advanced Statistical Programming for
Data Science, Analysis and Finance 1st Edition Thomas
Mailund
https://textbookfull.com/product/metaprogramming-in-r-advanced-
statistical-programming-for-data-science-analysis-and-finance-1st-
edition-thomas-mailund/
textboxfull.com

Advanced Object-Oriented Programming in R: Statistical


Programming for Data Science, Analysis and Finance 1st
Edition Thomas Mailund
https://textbookfull.com/product/advanced-object-oriented-programming-
in-r-statistical-programming-for-data-science-analysis-and-
finance-1st-edition-thomas-mailund/
textboxfull.com

Domain Specific Languages Made Easy MEAP V04 Meinte


Boersma

https://textbookfull.com/product/domain-specific-languages-made-easy-
meap-v04-meinte-boersma/

textboxfull.com

Practical Scala DSLs: Real-World Applications Using Domain


Specific Languages 1st Edition Pierluigi Riti

https://textbookfull.com/product/practical-scala-dsls-real-world-
applications-using-domain-specific-languages-1st-edition-pierluigi-
riti/
textboxfull.com

The Joys of Hashing: Hash Table Programming with C 1st


Edition Thomas Mailund

https://textbookfull.com/product/the-joys-of-hashing-hash-table-
programming-with-c-1st-edition-thomas-mailund/

textboxfull.com
Domain-Specific
Languages in R
Advanced Statistical Programming

Thomas Mailund
Domain-Specific
Languages in R
Advanced Statistical
Programming

Thomas Mailund
Domain-Specific Languages in R: Advanced Statistical Programming
Thomas Mailund
Aarhus N, Staden København, Denmark

ISBN-13 (pbk): 978-1-4842-3587-4   ISBN-13 (electronic): 978-1-4842-3588-1


https://doi.org/10.1007/978-1-4842-3588-1
Library of Congress Control Number: 2018947391

Copyright © 2018 by Thomas Mailund


This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or
part of the material is concerned, specifically the rights of translation, reprinting, reuse of
illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way,
and transmission or information storage and retrieval, electronic adaptation, computer software,
or by similar or dissimilar methodology now known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark
symbol with every occurrence of a trademarked name, logo, or image we use the names, logos,
and images only in an editorial fashion and to the benefit of the trademark owner, with no
intention of infringement of the trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if
they are not identified as such, is not to be taken as an expression of opinion as to whether or not
they are subject to proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of
publication, neither the authors nor the editors nor the publisher can accept any legal
responsibility for any errors or omissions that may be made. The publisher makes no warranty,
express or implied, with respect to the material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Steve Anglin
Development Editor: Matthew Moodie
Coordinating Editor: Mark Powers
Cover designed by eStudioCalamar
Cover image designed by Freepik (www.freepik.com)
Distributed to the book trade worldwide by Springer Science+Business Media New York,
233 Spring Street, 6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax (201) 348-4505,
e-mail orders-ny@springer-sbm.com, or visit www.springeronline.com. Apress Media, LLC is a
California LLC and the sole member (owner) is Springer Science + Business Media Finance Inc
(SSBM Finance Inc). SSBM Finance Inc is a Delaware corporation.
For information on translations, please e-mail editorial@apress.com; for reprint, paperback, or
audio rights, please e-mail bookpermissions@springernature.com.
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook
versions and licenses are also available for most titles. For more information, reference our Print
and eBook Bulk Sales web page at www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is
available to readers on GitHub via the book’s product page, located at www.apress.com/
9781484235874. For more detailed information, please visit www.apress.com/source-code.
Printed on acid-free paper
Table of Contents
About the Author��������������������������������������������������������������������������������vii
About the Technical Reviewer�������������������������������������������������������������ix

Chapter 1: Introduction������������������������������������������������������������������������1
Who This Book Is For���������������������������������������������������������������������������������������������1
Domain-Specific Languages���������������������������������������������������������������������������������2

Chapter 2: Matrix Expressions�������������������������������������������������������������9


Parsing Expressions��������������������������������������������������������������������������������������������10
Meta-Programming Parsing��������������������������������������������������������������������������14
Expression Manipulation�������������������������������������������������������������������������������������18
Optimizing Multiplication�������������������������������������������������������������������������������20
Expression Rewriting�������������������������������������������������������������������������������������23
Expression Evaluation�����������������������������������������������������������������������������������������27

Chapter 3: Components of a Programming Language������������������������31


Text, Tokens, Grammars, and Semantics�������������������������������������������������������������32
Specifying a Grammar����������������������������������������������������������������������������������������36
Designing Semantics������������������������������������������������������������������������������������������46

Chapter 4: Functions, Classes, and Operators������������������������������������55


The S3 Object-Oriented Programming System���������������������������������������������������56
Objects and Classes��������������������������������������������������������������������������������������56
Generic Functions������������������������������������������������������������������������������������������58

iii
Table of Contents

Operator Overloading������������������������������������������������������������������������������������63
Group Generics����������������������������������������������������������������������������������������������68
Precedence and Evaluation Order�����������������������������������������������������������������������70
Code Blocks��������������������������������������������������������������������������������������������������������73

Chapter 5: Parsing and Manipulating Expressions�����������������������������77


Quoting and Evaluating���������������������������������������������������������������������������������������78
Exploring Expressions�����������������������������������������������������������������������������������������84
Manipulating Expressions�����������������������������������������������������������������������������������94

Chapter 6: Lambda Expressions�������������������������������������������������������101


Anonymous functions���������������������������������������������������������������������������������������101
Experiments with Alternatives to the Syntax����������������������������������������������������104
Don’t Do This at Home��������������������������������������������������������������������������������������107

Chapter 7: Environments and Expressions���������������������������������������109


Scopes and Environments��������������������������������������������������������������������������������109
Default Parameters, Lazy Evaluation, and Promises�����������������������������������������114
Quotes and Non-standard Evaluation���������������������������������������������������������������124

Chapter 8: Tidy Evaluation����������������������������������������������������������������135


Quosures�����������������������������������������������������������������������������������������������������������136
Quasi-quoting���������������������������������������������������������������������������������������������������147

Chapter 9: List Comprehension��������������������������������������������������������159

Chapter 10: Continuous-Time Markov Chains����������������������������������167


Constructing the Markov Chain�������������������������������������������������������������������������170
Constructing a Rate Matrix�������������������������������������������������������������������������������174
Traces����������������������������������������������������������������������������������������������������������������177
Computing Likelihoods��������������������������������������������������������������������������������������180

iv
Table of Contents

Chapter 11: Pattern Matching����������������������������������������������������������183


Constructors������������������������������������������������������������������������������������������������������185
Pattern Matching����������������������������������������������������������������������������������������������196
Lists������������������������������������������������������������������������������������������������������������������203
Search Trees�����������������������������������������������������������������������������������������������������207

Chapter 12: Dynamic Programming�������������������������������������������������215


Parsing Expressions������������������������������������������������������������������������������������������221
Evaluating Expressions�������������������������������������������������������������������������������������229
Fixing the Evaluation Environment��������������������������������������������������������������������242

Chapter 13: Conclusion���������������������������������������������������������������������247

References����������������������������������������������������������������������������������������249

Index�������������������������������������������������������������������������������������������������251

v
About the Author
Thomas Mailund is an associate professor in bioinformatics at Aarhus
University, Denmark. He has a background in math and computer science.
For the past decade, his main focus has been on genetics and evolutionary
studies, particularly comparative genomics, speciation, and gene flow
between emerging species. He has published Beginning Data Science in
R, Functional Programming in R, and Metaprogramming in R, all from
Apress, as well as other books.

vii
About the Technical Reviewer
Colin Fay works for ThinkR, a French agency
focused on everything R-related.
During the day, he helps companies
take full advantage of the power of R by
providing training (from beginner to
expert), tools (packages, shiny apps…), and
infrastructure. His main areas of expertise
are software engineering, analytics, and data
visualization.
During the night, Colin is a hyperactive open source developer and an
open data advocate. You can find a lot of his work on his GitHub account
(https://github.com/ColinFay).
He is also active in the data science community in France, especially
in his home town Rennes, where he founded the data-blogging web site
Data-Bzh.fr, co-founded the Breizh Data Club association, and organizes
the Breizh Data Club Meetups.
You can learn more about Colin via his web site at https://colinfay.me,
and you can find him on Twitter at https://twitter.com/_ColinFay.
To learn more about ThinkR, please visit www.thinkr.fr/,
https://github.com/ThinkR-­open, and https://twitter.com/Thinkr_FR.

ix
CHAPTER 1

Introduction
This book introduces embedded domain-specific languages in R. The
term domain-specific languages, or DSL, refers to programming languages
specialized for a particular purpose, as opposed to general-purpose
programming languages. Domain-specific languages ideally give you
a precise way of specifying tasks you want to do and goals you want to
achieve, within a specific context. Regular expressions are one example
of a domain-specific language, where you have a specialized notation
to express patterns of text. You can use this domain-specific language to
define text strings to search for or specify rules to modify text. Regular
expressions are often considered very hard to read, but they do provide
a useful language for describing text patterns. Another example of a
domain-­specific language is SQL—a language specialized for extracting
from and modifying a relational database. With SQL, you have an
expressive domain-specific language in which you can specify rules as to
which data points in a database you want to access or modify.

Who This Book Is For


This book is aimed at experienced R programmers. Some of the concepts
we cover in this book are advanced, so at the very least you should be
familiar with functional and object-oriented programming in R (although
the next chapter will review the object-oriented programming features

© Thomas Mailund 2018 1


T. Mailund, Domain-Specific Languages in R,
https://doi.org/10.1007/978-1-4842-3588-1_1
Chapter 1 Introduction

we will use). It will be helpful to have some experience with ­meta-­


programming when it comes to evaluating expressions in contexts that
interact with the surrounding R code. However, Chapter 7 gives a crash
course in the techniques we will use in this book, so you should be able to
pick it up with a little effort from there.

D
 omain-Specific Languages
With domain-specific languages we often distinguish between “external”
and “embedded” languages. Regular expressions and SQL are typically
specified as strings when you use them in a program, and these strings
must be parsed and interpreted when your program runs. In a sense,
they are languages separated from the programming language you use
them in. They need to be compiled separately and then called by the
main programming language. They are therefore considered “external”
languages. In contrast, embedded domain-specific languages provide
domain-specific languages expressed in the general-purpose language
in which they are used. In R, the grammar of graphics implemented in
ggplot2 or the data transformation operations implemented in dplyr
provides small languages—domain-specific languages—that you can use
from within R, and you write the programs for these languages in R as well.
Embedded DSLs extend the programming language in which you are
working. They provide more than what you usually find in a framework
in the form of functions and classes as they offer a high level of flexibility
in what you can do with them. They are programming languages, after
all, and you can express complex ideas and tasks in them. They provide a
language for expressing thoughts in a specific domain, so they do not give
you a general programming language as the language you use them from,
but they do extend that surrounding language with new expressive power.
However, being embedded in the general-purpose language means that
they will follow the rules you are familiar with there—or mostly, at least,

2
Chapter 1 Introduction

since in languages such as R it is possible to modify the rules a bit using


so-called non-standard evaluation. You can expect the syntax of the
embedded DSL to follow the rules of the general-purpose language. The
semantics will be determined by the DSL, but when you write programs
in the DSL, the syntax is already familiar to you. If you implement a DSL
yourself, embedding it in a general-purpose language lets you reuse the
parsing and evaluation done by the general-purpose language so that you
can focus on designing the domain-specific language.
Implementing embedded domain-specific languages often involves
meta-programming; that is, it consists of treating the program you
are writing as data that you can manipulate from within the language
itself. This might sound more complicated than it is, but quite often,
it is reasonably straightforward to achieve. Using classes and operator
overloading, we can use R’s parser to parse embedded languages by simply
designing the language such that evaluating expressions automatically
parse them. This leaves us with data structures we, ourselves, have
defined, without us having to parse anything, and we can rewrite the
results of such parsed expressions in various ways before we evaluate them
to run the embedded program. Evaluating expressions can be relatively
straightforward or involve a deeper analysis of the parsed expressions.
To get a feel for what we can do with embedded domain-specific
languages, let’s consider a simple DSL: matrix multiplication (an example
we cover in more detail in Chapter 2). You might not think of matrix
expressions as much of a programming language, but the arithmetic
notation is highly efficient for expressing ideas in a limited domain. Just
imagine having to do mathematics without this notation. Of course, R
already supports this language—it has infix operators and the semantics
we associate with arithmetic expressions when we write them in an R
program. However, since matrix multiplication is a well-known task, it
serves as an excellent example to illustrate some of the things we can do if
we extend R with other smaller programming languages.

3
Chapter 1 Introduction

R already supports arithmetic with matrices, and if you use the


operator %*%, you can do matrix multiplication (if you use *, you will do
component-wise multiplication instead). Multiplications are done one at a
time, so if you have a series of them, such as this:

A %*% B %*% C %*% D

then the product will be computed from left to right, like this:

((A %*% B) %*% C) %*% D

For each multiplication, you produce a new matrix that will be used in
the next multiplication.
Now, matrix multiplication is associative, so you should be able to
set the parentheses in any way, as long as you respect the left-to-right
order of the matrices (matrix multiplication is not commutative, after
all), and you will get the same result. The running time, however, will
not be the same. We can do a small experiment to see this using the
microbenchmark package.

A <- matrix(1, nrow = 400, ncol = 300)


B <- matrix(1, nrow = 300, ncol = 30)
C <- matrix(1, nrow = 30, ncol = 500)
D <- matrix(1, nrow = 500, ncol = 400)

library(microbenchmark)
res <- microbenchmark(A %*% B %*% C %*% D,
                      ((A %*% B) %*% C) %*% D,
                      (A %*% (B %*% C)) %*% D,
                      (A %*% B) %*% (C %*% D),
                      A %*% (B %*% (C %*% D)),
                      A %*% ((B %*% C) %*% D))

options(microbenchmark.unit="relative")
print(res, signif = 3, order = "mean")

4
Chapter 1 Introduction

## Unit: relative
##                     expr  min   lq mean median
##  (A %*% B) %*% (C %*% D) 1.00 1.00 1.00   1.00
##  A %*% (B %*% (C %*% D)) 3.92 3.87 3.49   3.84
##      A %*% B %*% C %*% D 6.13 6.06 5.42   6.03
##  ((A %*% B) %*% C) %*% D 6.12 6.05 5.51   6.04
##  A %*% ((B %*% C) %*% D) 7.71 7.62 6.75   7.57
##  (A %*% (B %*% C)) %*% D 9.88 9.76 8.73   9.69
##    uq  max neval
##  1.00 1.00   100
##  3.62 1.41   100
##  5.57 2.06   100
##  5.61 2.35   100
##  7.00 2.30   100
##  8.99 3.71   100

Here, I’ve computed the matrix product in the five different possible
ways. There are six expressions, but the first two will compute the matrix
multiplication in the same order. With microbenchmark we compute each
expression 100 times and collect the time each evaluation takes. We collect
the time it takes to compute each expression, and here I have displayed
the running time relative to the fastest expression, sorted by the mean
evaluation time.
On average, there is almost a factor of ten between the fastest and
the slowest evaluation (for the slowest evaluations in the two cases the
difference is a factor of two, which is still a substantial relative difference).
There is something to be gained by setting parentheses optimally if we
multiply together several large matrices. The dimensions of matrices are
not necessarily known before runtime, however, so ideally we want to set
the parentheses when we evaluate expressions in an optimal way.

5
Chapter 1 Introduction

The approach we take in Chapter 2 is to delay the evaluation of


matrix multiplication and instead build a data structure for matrix
expressions, one we can evaluate later when we have the entire matrix
multiplication expression constructed. It is a simple DSL, but it contains
all the components we typically need in one: we need code for parsing
an expression and creating a representation of it, we need to do some
manipulation of expressions, and then we need to evaluate them.
For parsing expressions, we need to capture matrices and
multiplications. We wrap matrices in a class to make them objects of our
language, rather than plain R data.

m <- function(data) {
  structure(data,
            nrow = nrow(data),
            ncol = ncol(data),
            class = c("matrix_expr", class(data)))
}

The class matrix_expr is one we will use to overload the multiplication


operator, and we want all elements of this class to know their dimensions,
so when we wrap the data, we save the number of rows, nrow, and the
number of columns, ncol.
We also want to capture matrix multiplications, where we do not
evaluate the multiplication but simply save references to the matrices that
we want to multiply together.

matrix_mult <- function(A, B) {


  structure(list(left = A, right = B),
            nrow = nrow(A),
            ncol = ncol(B),
            class = c("matrix_mult", "matrix_expr"))
}

6
Chapter 1 Introduction

Of course, we do not want to write expressions as follows:

matrix_mult(matrix_mult(m(A), m(B), matrix_mult(m(C), m(D))))

so we overload the * operator:

`*.matrix_expr` <- function(A, B) {


  matrix_mult(A, B)
}

Now, this expression:

m(A) * m(B) * m(C) * m(D)

is our new syntax for the matrix multiplication, shown here:

A %*% B %*% C %*% D

except that the former expression only constructs a data structure


representing the expression. It does not evaluate it.
When we need to evaluate a matrix multiplication, we want to analyze
the delayed evaluation and rearrange the multiplication to get the optimal
performance. In Chapter 2 we will implement the functions rearrange_
matrix_mult and eval_matrix_mult that do this. Here, we just define a
function, v, for evaluating a matrix multiplication:

v <- function(expr)
    eval_matrix_expr(rearrange_matrix_expr(expr))

We can compare this automatic parentheses setting procedure with


the default evaluation and the optimal evaluation order we saw earlier.

res <- microbenchmark(A %*% B %*% C %*% D,


                      (A %*% B) %*% (C %*% D),
                      v(m(A) * m(B) * m(C) * m(D)))

options(microbenchmark.unit="relative")
print(res, signif = 3, order = "mean")

7
Chapter 1 Introduction

## Unit: relative
##                          expr  min   lq mean
##       (A %*% B) %*% (C %*% D) 1.00 1.00 1.00
##  v(m(A) * m(B) * m(C) * m(D)) 1.13 1.19 1.37
##           A %*% B %*% C %*% D 6.13 6.09 5.65
##  median   uq  max neval
##    1.00 1.00 1.00   100
##    1.23 1.26 1.19   100
##    6.08 5.99 2.19   100

The automatic solution is only slightly slower than the optimal solution
and about a factor of six better than the default evaluation.

8
CHAPTER 2

Matrix Expressions
In the next chapter we discuss computer languages in a more theoretical
way, but here we will consider a concrete case—the matrix expressions
mentioned in Chapter 1. This example is a relatively simple domain-­
specific language, but parsing matrix expressions, optimizing them, and
then evaluating them are all the phases we usually have to implement in
any DSL, and the implementation will also have examples of most of the
techniques we will cover in more detail later. The example will use some
tricks that I will not explain until later in the book, so some aspects might
not be evident at this point, but the broader strokes should be and will
ideally serve as a sneak peek of what follows in future chapters.
Our goal for writing a language for matrix expressions is to improve
upon the default performance of the built-in matrix expressions. We
achieve this by taking a more global view of expressions than R does—R
will handle each operator one at a time from left to right, but we will
analyze expressions and rearrange them to improve performance. These
are the steps we must take to do this:

1. Parse expressions into data that we can manipulate.

2. Rearrange the expressions into more efficient


expressions.

3. Provide a way to evaluate the expressions.

© Thomas Mailund 2018 9


T. Mailund, Domain-Specific Languages in R,
https://doi.org/10.1007/978-1-4842-3588-1_2
Chapter 2 Matrix Expressions

In this chapter, we use the following library:

library(microbenchmark)

P
 arsing Expressions
To keep things simple, we will only consider matrix multiplication and
matrix addition. We do not include scalar multiplication or inverting or
transposing matrices or any other functionality. Adding more components
of the expression language in the example will follow the same ideas as
we need for multiplication and addition. It will not teach us anything new
regarding embedding DSLs in R. When you understand the example, you
will be able to do this easily yourself.
With these restrictions, we can say that a matrix expression is either
just a matrix, the product of two matrix expressions, or the sum of two
matrix expressions. We can represent this as a class hierarchy with one
(abstract) superclass representing expressions and three (concrete)
subclasses for actual data, products, and sums. If you are not familiar with
object-oriented programming in R, we will have a short guide to everything
you need to know in Chapter 4. Constructors for creating objects of the
three concrete classes can look like these:

m <- function(data) {
  structure(list(data = data),
            nrow = nrow(data),
            ncol = ncol(data),
            def_expr = deparse(substitute(data)),
            class = c("matrix_data", "matrix_expr"))
}
matrix_mult <- function(A, B) {

10
Chapter 2 Matrix Expressions

  structure(list(left = A, right = B),


            nrow = nrow(A),
            ncol = ncol(B),
            class = c("matrix_mult", "matrix_expr"))
}
matrix_sum <- function(A, B) {
  structure(list(left = A, right = B),
            nrow = nrow(A),
            ncol = ncol(B),
            class = c("matrix_sum", "matrix_expr"))
}

We just wrap the parameters of the constructors in a list and set


the appropriate class attributes, and we store the number of rows and
number of columns because we will need them when optimizing matrix
multiplication, as we saw in Chapter 1.
The only purpose of the def_expr attribute we set in the m function is
pretty printing. It makes the output of the expressions we manipulate in
the following pages easier to follow. Strictly speaking, we do not need any
pretty printing for manipulating expressions, but it does make debugging
easier, so I tend always to write some code for that. For the matrix
expressions, we can use the following code:

toString.matrix_data <- function(x, ...) {


  paste0("[", attr(x, "def_expr"), "]")
}
toString.matrix_mult <- function(x, ...) {
  paste0("(", toString(x$left), " * ", toString(x$right), ")")
}
toString.matrix_sum <- function(x, ...) {
  paste0("(", toString(x$left), " + ", toString(x$right), ")")
}
print.matrix_expr <- function(x, ...) {

11
Chapter 2 Matrix Expressions

  cat(toString(x), "\n")
}

Using the constructors and the pretty-printing code, we can try to


construct a small expression.

A <- matrix(1, nrow = 10, ncol = 20)


B <- matrix(1, nrow = 20, ncol = 10)
C <- matrix(1, nrow = 10, ncol = 10)

matrix_sum(matrix_mult(m(A), m(B)), m(C))

## (([A] * [B]) + [C])

There is nothing in what we have done so far that qualifies as providing


a language as such. We have just implemented a few constructor functions.
However, if we overload the multiplication and addition operators for matrix
expressions, we get something that starts to resemble a language at least.

`*.matrix_expr` <- function(A, B) {


  stopifnot(ncol(A) == nrow(B))
  matrix_mult(A, B)
}
`+.matrix_expr` <- function(A, B) {
  stopifnot(dim(A) == dim(B))
  matrix_sum(A, B)
}

With these, we can write the same expression more familiarly.

m(A) * m(B) + m(C)

## (([A] * [B]) + [C])

12
Chapter 2 Matrix Expressions

I have put some assertions—the calls to stopifnot()—into the code


for the operators to make sure that the dimensions of the matrices involved
in operators are valid. We could also have placed these in the constructor
functions, but later, we will manipulate expressions where we know that
the dimensions are valid, so we do not need to check them there. We do
not expect a user to call the constructors directly but use the operators, so
this is the natural place to put the checks.
We use the dim function for the sanity check in the addition operator,
so we need a version of this that works on matrix expressions. It could look
like this:

dim.matrix_expr <- function(x) {


  c(attr(x, "nrow"), attr(x, "ncol"))
}

You might be wondering why we need the m function. After all, it does
not contribute anything to expressions instead of just wrapping matrices.
Could we just use the matrices directly? The answer is no, and it has to
do with how we use operator overloading. For * and + to be the matrix
expression versions, we need the first arguments given to them to be a
matrix expression. If we wrote simply this:

A * B + C

## Error in A * B: non-conformable arrays

we would be invoking the operators for R’s matrix class instead. And since
* is not matrix multiplication (for that you need to use %*% because the *
operator is component-wise multiplication), you get an error.
We need a way of bootstrapping us from R’s matrices to the matrices in
our expression language. That is what we use m for.

13
Chapter 2 Matrix Expressions

M
 eta-Programming Parsing
Using an explicit function such as m to bootstrap us into the matrix
expression language is the simplest way to use R’s own parser for our
benefits, but it is not the only way. In R, we can manipulate expressions as
if they were data, a feature known as meta-programming and something we
return to in Chapter 5. For now, it suffices to know that an expression can
be explored recursively. We can use the predicate is.name to check whether
the expression refers to a variable, and we can use the predicate is.call
to check whether it is a function call—and all operators are function calls.
So, given an expression that does not use the m function and thus does not
enter our DSL, we can transform it into one that goes like this:

build_matrix_expr <- function(expr) {


  if (is.name(expr)) {
      return(substitute(m(name), list(name = expr)))
  }

  if (is.call(expr)) {
      if (expr[[1]] == as.name("("))
        return(build_matrix_expr(expr[[2]]))
      if (expr[[1]] == as.name("*") ||
          expr[[1]] == as.name("%*%")) {
          return(call('*',
                      build_matrix_expr(expr[[2]]),
                      build_matrix_expr(expr[[3]])))
      }
      if (expr[[1]] == as.name("+")) {
          return(call('+',
                      build_matrix_expr(expr[[2]]),
                      build_matrix_expr(expr[[3]])))
      }
  }

14
Chapter 2 Matrix Expressions

  stop(paste("Parse error for", expr))


}

In this implementation, we consider both * and %*% matrix


multiplication so that we would consider an R expression that uses
matrix multiplication as such. Notice also that we consider calls that are
parentheses. Parentheses are also function calls in R, and if we want to
allow our language to use parentheses, we have to deal with them—like
here, where we just continue the recursion. We did not have to worry
about that when we explicitly wrote expressions using m and operator
overloading because there R already took care of giving parentheses the
right semantics.
For this function to work, it needs a so-called quoted expression. If
we write a raw expression in R, then R will try to evaluate it before we
can manipulate it. We will get an error before we even get to rewrite the
expression.

build_matrix_expr(A * B)

## Error in A * B: non-conformable arrays

To avoid this, we need to quote the expression.

build_matrix_expr(quote(A * B))

## m(A) * m(B)

We can avoid having to explicitly quote expressions every time we


call the function by wrapping it in another function that does this for us.
If we call the function substitute on a function parameter, we get the
expression it contains so that we can write a function like this:

parse_matrix_expr <- function(expr) {


  expr <- substitute(expr)
  build_matrix_expr(expr)
}

15
Chapter 2 Matrix Expressions

Now, we do not need to quote expressions to do the rewriting.

parse_matrix_expr(A * B)

## m(A) * m(B)

This isn’t a perfect solution, and there are some pitfalls, among which
is that you cannot use this function from other functions directly. The
substitute function can be difficult to work with. The further problem
is that we are creating a new expression, but it’s an R expression and not
the data structure we want in our matrix expression language. You can
think of the R expression as a literate piece of code; it is not yet evaluated
to become the result we want. For that, we need the eval function, and
we need to evaluate the expression in the right context. Working with
expressions, especially evaluating expressions in different environments,
is among the more advanced aspects of R programming, so if it looks
complicated right now, do not despair. We cover it in detail in Chapter 7.
For now, we will just use this function:

parse_matrix_expr <- function(expr) {


  expr <- substitute(expr)
  modified_expr <- build_matrix_expr(expr)
  eval(modified_expr, parent.frame())
}

It gets the (quoted) expression, builds the corresponding matrix


expression, and then evaluates that expression in the “parent frame,”
which is the environment where we call the function. With this function,
we can get a data structure in our matrix language from an otherwise
ordinary R expression.

parse_matrix_expr(A * B)

## ([A] * [B])

16
Chapter 2 Matrix Expressions

The approach we take here involves translating one R expression into


another to use our m function to move us from R to matrix expressions.
This involves parsing the expression twice, once when we transform it
and again when we ask R to evaluate the result. The approach is also
less expressive than using the m function directly. We can call m with any
expression that generates a matrix, but in the expression transformation,
we only allow identifiers.
As an alternative, we can build the matrix expression directly using
our constructor functions. We will use matrix_mult and matrix_sum
when we have a call that is *, %*%, or +, and otherwise, we will call m. This
way, any expression we do not recognize as multiplication or addition
will be interpreted as a value we should consider a matrix. This approach,
however, adds one complication. When we call function m, we need to call
it with a value, but what we have when traversing the expression is quoted
expressions. We need to evaluate such expressions, and we need to do so
in the right environment. We will need to pass an environment along with
the traversal for this to work.

build_matrix_expr <- function(expr, env) {


  if (is.call(expr)) {
    if (expr[[1]] == as.name("("))
      return(build_matrix_expr(expr[[2]], env))
    if (expr[[1]] == as.name("*") || expr[[1]] == as.name("%*%"))
      return(matrix_mult(build_matrix_expr(expr[[2]], env),
                         build_matrix_expr(expr[[3]], env)))
    if (expr[[1]] == as.name("+"))
      return(matrix_sum(build_matrix_expr(expr[[2]], env),
                        build_matrix_expr(expr[[3]], env)))
  }
  data_matrix <- m(eval(expr, env))
  attr(data_matrix, "def_expr") <- deparse(expr)
  data_matrix
}
17
Chapter 2 Matrix Expressions

Most of this function should be self-explanatory, except for where we


explicitly set the def_expr attribute of a data matrix. This is the attribute to
be used for pretty printing, and when we call the m function, it is set to the
literate expression we called m with. This would be eval(expr, env) for all
matrices we create with this function. To avoid that, we explicitly set it to
the expression we use in the evaluation.
Once again, we can wrap the function in another that gets us the
quoted expression and provide the environment in which we should
evaluate expressions.

parse_matrix_expr <- function(expr) {


  expr <- substitute(expr)
  build_matrix_expr(expr, parent.frame())
}

parse_matrix_expr(A * B + matrix(1, nrow = 10, ncol = 10))

## (([A] * [B]) + [matrix(1, nrow = 10, ncol = 10)])

There is more to know about manipulating expressions, especially


about how they are evaluated, but we will return to that in later chapters.

Expression Manipulation
Our goal for writing this matrix DSL is to optimize evaluation of these
matrix expressions. There are several optimizations we can consider, but
R’s matrix implementation is reasonably efficient already. It is hard to beat
if we try to replace any computations by our own implementations—at
least as long as we implement our alternatives in R. Therefore, it makes
sense to focus on the arithmetic rewriting of expressions.

18
Chapter 2 Matrix Expressions

We can rewrite expressions recursively and use a generic function with


specializations for the three concrete classes we have. A template (that
does not do anything yet) would look like this:

rearrange_matrix_expr <- function(expr) {


  UseMethod("rearrange_matrix_expr")
}
rearrange_matrix_expr.matrix_data <- function(expr) {
  expr
}
rearrange_matrix_expr.matrix_mult <- function(expr) {
  matrix_mult(rearrange_matrix_expr(expr$left),
              rearrange_matrix_expr(expr$right))
}
rearrange_matrix_expr.matrix_sum <- function(expr) {
  matrix_sum(rearrange_matrix_expr(expr$left),
             rearrange_matrix_expr(expr$right))
}

These functions traverse a matrix expression and return the same


expression structure. We can modify the functions based on patterns of
expressions, however, to start rearranging.
We can make some reasonable guesses at how many operations are
needed to evaluate an expression from these two rules: 1) multiplying an
n × k matrix to a k × m matrix involves n × k × m operations, and 2) adding
two n × m matrices together involves n × m operations. If we can do any
rewriting of an expression that reduces the number of operations we have
to do, then we are improving the expression.
There are some obvious patterns we could try to match and rewrite.
For instance, we should always prefer (A + B)C over AC + BC. However, we
can probably expect that the programmer writing an expression already
knows this, so we will likely get little to gain from such obvious rewrites.
Where we might get some performance improvements is when expressions

19
Chapter 2 Matrix Expressions

consist of several matrices multiplied together. There, the order of


multiplications matters for the number of operations we have to perform,
and the optimal order depends on the dimensions of the matrices; we
cannot merely look at the arithmetic expression and see the obvious way of
setting parentheses to get the best performance.

Optimizing Multiplication
Before we start rewriting multiplication expressions, though, we should
figure out how to find the optimal order of multiplication. Let’s assume
that we have this matrix multiplication: A1 × A2 × … × An. We need to set
parentheses somewhere, say (A1 × A2 × …Ai) × (Ai+1…× An), to select the last
matrix multiplication. If we first multiply together, in some order, the first i
and the last n – i matrices, the last multiplication we have to do is the product
of those two. If the dimensions of (A1 × …Ai) are n × k and the dimensions of
(Ai+1…× An) are k × m, then this approach will involve n × k × m operations
plus how long it takes to produce the two matrices. Assuming that the best
possible way of multiplying the first i matrices involves N1,i operations and
assuming the best possible way of multiplying the last n – i matrices together
involves Ni+1,n operations, then the best possible solution that involves setting
the parentheses where we just did involves N1,i + Ni+1,n +n × k × m operations.
Obviously, to get the best performance, we must pick the best i for setting
the parentheses at the top level, so we must minimize this expression for i.
Recursively, we can then solve for the sequences 1 to i and i + 1 to n to get
the best performance.
Put another way, the minimum number of operations we need to
multiply matrices Ai,Ai+1,…,Aj can be computed recursively as Ni,j = 0 when
i = j and

{ }
N i , j = min N i ,k + N k +1, j + nrow ( Ai ) ´ ncol ( Ak ) ´ ncol ( A j )
k

20
Chapter 2 Matrix Expressions

otherwise. Actually computing this recursively would involve recomputing


the same values many times, but using dynamic programming we can
compute the Ni,j table efficiently, and from that table we can backtrack and
find the optimal way of setting parentheses as well.
In the following implementation, we assume that we have such a list
of matrices as input. We then collect their dimensions in a table, dims,
for easy access. Then, we simply create a table to represent the Ni,j values
and fill it using the previous equation. Once we have filled the table, we
backtrack through it to work out the optimal way of multiplying together
the matrices from 1 to n, given the dimensions, table, and matrices.

arrange_optimal_matrix_mult <- function(matrices) {


  n <- length(matrices)
  dims <- matrix(0, nrow = n, ncol = 2)
  for (i in seq_along(matrices)) {
    dims[i,] <- dim(matrices[[i]])
  }

  N <- matrix(0, nrow = n, ncol = n)


  for (len in 2:n) {
    for (i in 1:(n - len + 1)) {
      j <- i + len - 1
      k <- i:(j - 1)
N[i,j] <- min(dims[i,1]*dims[k,2]*dims[j,2] + N[i,k] +
      
N[k + 1,j])
    }
  }

  # Backtrack through the table. This function will


  # be defined shortly.
  backtrack_matrix_mult(1, n, dims, N, matrices)
}

21
Random documents with unrelated
content Scribd suggests to you:
XXIV.

Az egyetemes: mint természeti


törvény.

A természetről szólunk, mely legyőzhetetlen hatalmát az egyes


ember ellen zúdítja. Miféle jelenségek fejezik ki e hatalmat
legszembeötlőbben, legérezhetőbben, legmegrenditőbb alakban?
Kétségkívül a nagy természeti forradalmak s elemi csapások. Velök
szemben a legnagyobb emberi erő is tehetetlen s pusztulásra szánt.
Az özönvíz, melynek borzalmait Michelangelo festette a
Sixtinában; a természeti erőknek az a rettentő háborgása, mely
Sodomát és Gomorát tűzesővel rombolta szét s az egész Sziddim
völgyét a holttenger hullámai alá temette; a Vezuv borzasztó
kitörése, mely Pompejit és Herculanumot izzó hamuval borította el;
az iszonyú pestisek, melyeknek Thukydides és Boccaccio oly
megrendítő rajzát adják; éhségek a milyet Manzoni ír le: ezek és
hasonlók, földrengések, tengeri viharok, tűzvészek, vízáradások s
mindenekelőtt a halál tartoznak ide. Az emberi szellem mindebben
az egyetemes nyilatkozását, isten akaratát látja. A bennök rejlő
veszélylyel daczolást istenkisértésnek mondjuk.
A természeti hatalmaknak ilyen ellenállhatatlanul romboló és
megrémítő jelenségeit a költők gyakran szövik be motivumul
cselekvényeikbe, nem mint a tragikai katasztrófa tényezőit, az
egyetemes végső győzelmének fegyverét, hanem csak általában a
tragikai hangulat és benyomás emelésére. Az emberi tehetséget
meghaladó hatalmak jelentkezését éreztetik bennök, az emberi erők
harczának mintegy sötét hátterét, mely mindent eltiporni képes s
mindent magába olvasztani készűl. Jókai különösen feltünő kedvvel
és gyakran sző be regényeibe ilyen indítékokat: nevezetes elemi
csapásokat, emlékezetes természeti veszedelmeket. Igy dolgozta föl
az 1763. komáromi földrengést (Elátkozott család), az 1831. felvidéki
halálos járványt (Régi jó táblabirák), az 1838. budapesti nagy árvizet
(Kárpáthy Zoltán) s egy tiszai áradást (Új földesúr), az 1863.
országos inséget (Szerelem bolondjai) s egyebeket. Az északi
ballada is szereti az ilyen vészes mozzanatokat. Van egy német
eszthetikus, Grube, ki Goethe balladáiról és Schiller
románczairól írt könyvében, «a természet elemi erőinek közvetetlen
nyilatkozását s hatásukat az emberi lélekre» a ballada
szükségképeni tartalmául jelöli ki s épen ezekben találja egyik
sajátos, a rokon költői fajoktól megkülönböztető vonását.
Ránk nézve azonban fontosabbak a tragikai költők. Julius
Caesarban a gyilkosságot megelőző éj a borzalmak egész sorával
terhes. A földtömeg úgy reszket, mint a nád s gyilkos tűzzápor állja
útját az embereknek: Casca és Calpurnia festik részleteit. A
megreműlt oroszlán az utczán kölykezik s az éjmadár a köztéren
víjjog és huhog; menekülők csoportja lángban ég; a sírok
megnyilnak s felvetik holtaikat; a fellegek között tüzes vad férfiak
harczolnak, hogy vér húll le a Capitoliumra. Vészhirdető jelek a föld
szakának, melyre szállanak. A boldogtalan Lear király körül, ki a
fenyéren bolyong, vad förgetegben tombol a természet. Kent
mondja, hogy mióta férfi lett, ilyen tűzáradást, a mennydörgésnek ily
szörnyű kitörését s ily iszonyú vihar dörömbölését nem hallotta. Míg
V. László álmatlanúl küzködik lelkiismeretével, a sűrű, sötét éjben
dühöng a déli szél s Budavár magas tornyán élesen csikorog az
érczkakas; dörög a menny s a megszakadó felhő tüzet, patakot,
zugó sebes özönt áraszt. Minde képekben, tüneményekben a
természet nem egészen vak és oktalan erő gyanánt jelenik meg,
hanem bizonyos erkölcsi, vagy legalább az erkölcsivel érintkező
hatalom kifejezése gyanánt. Julius Caesarban a természet félelmes
rombolása valóban egy nagy ember kényszerű vesztét hirdeti, ki
félelmessé lett az erkölcsi rendre.
Koldús ha vész, nem tűn fel üstökös.
Ha fejdelemnek halni kell,
Lánggal jelenti azt az ég maga.

Learben már egy lépéssel odább jutunk az erkölcsi felfogás felé. Az


ősz király így beszél az elemek csatája közt:

A nagy istenek, kik ily réműletes


Dörömbölést tesznek fejünk felett,
Hadd leljék fel most ellenségöket.
Reszkess, nyomorú, kit még utól nem ért
A törvény keze eltitkolt bűnödért!
Nyilatkozzál, elzárkozott bűn,
S feltárva rejlő tartalmad, kiálts,
Hogy irgalomra bird ez iszonyú
Törvényszolgákat.

A dühöngő elemek tehát törvényszolgák, kik a rejtező vétket


kutatják. Az erkölcsi felfogás még homályos: egy mindentudó
igazságszolgáltatásnak keresnie kell a bűnösöket, az istenek nem
ismerik ellenségeiket; de a természeti világ vonatkoztatása az
erkölcsire, s e vonatkoztatásban az erkölcsi mag már szembetünő.
Még inkább az V. Lászlóban. A vihar itt az egyetemesnek
háromszoros erejű és jelentőségű kifejezése. Egy az, a mire
Greguss oly szépen utal: a külső képben mutatott belső. «A
háborgó természet a király háborgó lelkének külső képe: az ő
lelkében is a bősz elemek tusakodnak, üvölt a szél, csapkod a zápor,
villámlik és mennydörög, csakhogy benne a rossz lelkiismeret
mennydörgése szól, a czikázó villám az ő esküszegését világítja
meg rémesen belső valóját a késő bánat zápora verdesi, azon
csitíthatatlan félelem szélvésze járja át, hogy véres itéletének átka
előbb-utóbb mégis eléri, s a zúgó elemek mintha egyre a megsértett
nemzet boszúállását zúgnák fülébe.» Ez egy; de az elemek
felzúdulása érezteti velünk bizonyos közvetetlenségben is az ég
haragját a zsarnok ellen, ki ártatlan vért ontott. Maga is érzi, hogy a
szolga biztatása: «csupán a menny dörög» ránézve nem
vigasztalás, hanem szörnyű itélet. Az egyetemesnek ez a
közvetetlen nyilatkozása nemcsak a gonosznak vesztét hirdeti,
hanem támogatást is a jóknak: módot nyújt a fogoly Kanizsa és
Rozgonyi menekűlésére. A természeti és erkölcsi mind közelebb
jutnak egymáshoz, amannak tüneményeiben egyre világosabb
kifejezésre jut emez. A Golgotha tragédiájának rémes sceneriája: a
meghomályosodó nap, a templomnak ketté hasadó kárpitja, a
földindulás, a megrepedező kősziklák és megnyilatkozó sírok, a
kettőnek teljes egybeolvadását mutatják a keresztyén
világnézletben.
A hol nem jut is az egyetemesben az erkölcsi felfogásnak ily tág
tér, ily határozó befolyás: az emberi szellem ott sem nyugszik meg
egészen magukban a puszta természeti tüneményekben, mint merő
esetlegekben. Minden erkölcsi vonatkoztatás tulajdonképen
magyarázatát keresi s okát igyekszik megtalálni a jelenségeknek. A
romboló, vészes erők nyilatkozását eredményekül, hatásokul fogva
fel, általánosítható magyarázatul előáll a sors, a végzet képzete. A
fátum, mint az egyéni önállóság, szabadság, törekvés ellentéte s
tagadása. A természeti törvény, mint az egyetemesnek uralkodó
tartalma, mint az élet legfőbb kormányzója jelenik meg e
felfogásban: általános romboló hatalom, az embernek örök
ellensége. Az ősi görög felfogás szerint még az istenek is, kik
voltakép e törvény képviselői, egyszersmind alárendeltjei is.
Aeschylos Prometheusában olvassuk:

Prometheus: Furfang a Kényszer ellenébe gyönge.


Kar: S ki az, ki Kényszer útait kiszabja?
Prom. Három Moira és a nem felejtő Erinnysek.
Kar: S gyengébb Zeus miként ők?
Prom. A végzet ő reá se tesz kivételt.

Hogy mennyire tele volt képzeletök a végzettel, kitetszik abból, hogy


mily sokképen nevezték el fogalmát. Adraszteia, moira, pótmosz,
aisza, heimarmené, peprómené: mind őt jelentik.
Kikerűlhetetlenűl találkozik vele mindenki a halálban. Az
egyetemes mulandóságnak e komor gondolatát tolmácsolja a
Viharban Prospero, midőn a Ferdinand és Miranda előtt felidézett
csodalátványok eltűnnek:
A mint e látszat lenge szövete:
Az égverő tornyok, nagy paloták,
Dús templomok, maga e földgolyó,
S mi rajta van, mind semmivé oszol,
És mint e hiú látmány, nyomtalan
Eltűnik. Olyanok vagyunk mi is, mint
Az álmok anyagja: kurta életünk
Keretje álom.

Mindenre s mindenkire az elmúlás, a halál vár. A buddhista


mithologia Marája a világ s a testi gyönyörök istene és egyszersmind
a halál fejedelme: mert a ki élni és szeretni akar, a természetnek
adós a halállal. Annak titkos erejéből vette életét, annak tartozik
vele. Hiába a zúgolódás, a csalfaság, a küzdelem ellene: minden
egyéni lét ára az elmúlás. A természeti kényszernek ez
egyetemességében, épen az egyetemességből fakad a
megnyugvásnak némi forrása. Abból a gondolatból, hogy «egy
ember sem múlhatja a sírvermet, mind ahhoz járók vagyunk.»
Schiller vigasztalódása elhúnyta előtt: a halál nem lehet rossz,
mert hisz általános. A halálnak ez általánossága, az emberi sors
közössége enyhíti félelmességét s magyarázza az emberi léleknek
bizonyos végletes érzések közé vettetését vele szemben. Az
egyiptomiak víg lakomáikon körülhordozzák rokonaik múmiáit. A
müncheni nép egy középkori pestis iszonyú pusztításai között dalra
gyújt, tánczra kerekedik és neveti a halált. Élvezni akarja az életből
azt a keveset, a mi hátra van; de erre az élvezetre csak abból a
gondolatból meríthet erőt, képességet, hogy: íme senkinek sem
megy különben, együtt és egyenlő módon vesznek el mindannyian.
A természeti kényszernek ez a személyválogatást nem ismerő
pártatlansága, az élet igaztalanságaival szemben, vigasztaló is. A
földi sors különbözéseit, a hatalom és nyomor, az élvezet és
szűkölködés kiáltó ellentéteit a vég közössége, a benne érvényesűlő
föltétlen egyenlőség által, mintegy kiengeszteli. Erdélyi János
Csontvazának szavai:

Gőgben fejed ki hordod magasan,


Vagy szolga lelked csúszik aljasan,
Emlékezzél meg, eltávozva, rám:
A legjobb leczkét néked én adám, –

nemcsak megfélemlítő leczkét, hanem vigasztaló eszmét is rejtenek


magukban. Megpendítik a haláltánczok alapgondolatát, melyek a
legtöbb műtörténetíró szerint hasonló tárgyú drámai előadásokból,
párbeszédekből vették motivumaikat. Az egyházi, különösen a
dominikánus művészet, a legiszonyúbb alakban tüntette föl a halált,
mint az utolsó itélet ama borzalmainak ajtónállóját, melyeket
Orcagna és iskolája a fantaziának oly rémes gazdagságával
ábrázolt. E felfogás ellen, megragadva a halál pártatlanságában rejlő
vigasztaló mozzanatot, visszahatott a néphumor s belőle fakadtak a
háromszáz éven át divatozott haláltáncz-cziklusok. Közülök csak a
leghíresebbet, Holbeinét, említsük. Az átalakulásban forrongó
középkori társadalom visszásságai, elnyomásai, igaztalanságai a
művész lelke előtt egy félszáz képre terjedő sorozatban tűnnek föl.
Mindegyiknek közös megoldása a halál. Az erőszakos, leleményes,
ravasz és tréfás halál mindenütt az úr: a páthosz, humor, irónia
bennök egyiránt az élet semmisségét példázza. Pápa és barát,
császár és koldús, lovag és rabló, boldog menyasszony és bukott
kártyás, földmíves és hajós mind egy végre jut; a csont-ember
ugyanabba a verembe taszítja, vezeti, csalja őket. Csak a szegény
Lázárt, ki esdekelve hívja, ezt a mindenkitől elhagyottat, kerűli ő is.
De a halál igazában irgalmasabb, mint a művészi szeszély e képén.
Pártatlanságában még ott is, a hol szembetünőleg igaztalan, van
valami vigasztaló. Ott, a hol az erő teljességében, az ifjuság
hevében s a szépség fényében ragyogó életet dönt romba. Azt a
gondolatot, mely a természeti kényszernek ily durva
erőszakosságaival szemben is megnyugvást, sőt fölemelkedést
keres, soha senki sem fejezte ki szebben, mint Goethe, Schiller
kora halála fölött ejtette ő e görög szellemű szózatot: «Boldognak
mondhatjuk őt, hogy az emberi lét magasáról szállott a dicsőűltek
közé. Az aggkor bajait, a lelki erők fogyatkozását nem érezte. Férfi
gyanánt élt és teljes férfi erejében költözött el. Az az előny jutott
osztályrészeül, hogy az utókor emlékezetében örökké deréknek és
erőteljesnek tűnjék fel. Mert az ember abban az alakban bolyg az
árnyak között, melyben a földet elhagyta s így marad meg nekünk
Achilles örökké küzdő ifjúnak. Hogy Schiller korán halt meg, annak
mi is hasznát látjuk. Sírjából erősíteni fog erejének sugalma s eleven
ösztönt ébreszt bennünk, hogy a mit ő kezdett, mindig tovább és
tovább folytassuk. Igy él ő majd abban, a mit akart és tett, népének
és az emberiségnek.» Ezek Goethe szavai. Őt hallva, fölmerűl
lelkünkben a mi költőnk képe. Petőfié, a mint az ifjúság, boldogság
és dicsőség sugaraitól övezve, kezében lanttal és karddal, eltűnt
szemeink elől, hogy örökké így, ebben a fenséges alakban,
maradjon szemeink előtt.
Magában a halálban, mint ilyen általános, nagyot és kicsinyt
egyaránt sújtó nyilatkozásában a természeti törvénynek, még nem
találhatjuk meg az igazi tragikai mozzanatot, mint a hogy Zeising
állítja. Azzá csak ott emelkedik, a hol legyőzhetetlen ereje valami
kiválósággal, a szépség, hatalom, ifjúság, szerencse erejével
mérkőzik s ezt tiporja el. Az élet öröme, a törekvések sikere, a
hatalom birtoka minél inkább elfeledtetik az egyénnel létének
föltételességét, azt, hogy egy megmásíthatatlan természeti törvény
uralkodása alatt áll: annál közelebb jut sorsa teljességéhez, annál
hirtelenebb veszély fenyegeti s annál megrendítőbb lesz bukása. A
sorsnak e mennykőcsapásai, melyek váratlanúl sújtják azt, a mi
kimagaslik, mint a villám a tornyok csúcsait, hegyek ormait s fák
sudarát: tragikai megrendűlést idéznek elő. Ez az, a mit Vischer a
világtörvény, az universum tragikumának nevez, universum alatt
értvén «a tragikai összfoglalatot, complexust, mivel itt a természeti
alap lép előtérbe, mig az erkölcsi szükségességnek föléje emelkedő
világa, még csak fejletlenül jelentkezik csirájában, úgy hogy inkább
természeti viszonynyal mint ethikaival van dolgunk.» Az egyéni
kiválóság oly természetű, hogy nem sért erkölcsi eszmét, nem bontja
vétségbeli ütközéssel az egyetemes öszhangját: egyszerűen a
természeti kényszer nehezedik rá s érvényesűl rajta. A magasban,
hová ifjú erő, szépség hiv, boldogság emel, veszélyes viharok
járnak: az, a ki oda jut fel, könnyen találkozhatik velök. Az esetleg,
az ellenséges balvégzet rohanja meg, mint Adonist a vadkan, mely
Michelangelonak bargelloi szobrában is ott vicsorítja agyarait a
haldokló ifjú mellett. A kedves Linost kutyák szaggatják szét,
Bormost a vízár ragadja el. Az esetlegnek, a véletlennek az ide
tartozó jelenségeknél rendesen nagy szerepe van. Nem történvén
valóságos támadás az egyetemes ellen, nem érvén ezt sérelem egy
bizonyos határozott ponton, a honnan visszahatása kiindúl:
természetesen hiányzani fog ebből a tiszta, szemmel látható
okozatosság.
Vörösmarty Szép Ilonkája, a naiv, érzelmes bájnak örökszép
képe, a tragikum e formájának adja példáját, mint a székely
balladákban Kádár Kata s Fogarasi István huga is. Ilonka ártatlan
voltától ép oly távol van a vétség, mint a menekvés lehetősége.
Hiába keresünk benne csak annyi tévedést is, a mennyit Melindában
találtunk: neki módja sem lenne védeni magát. Erősebb kihívást még
kevésbbé fogunk találni. Nem csábít, sőt nem is csábíttatik: a Vértes
vadonában véletlen esik találkozása az ismeretlen királylyal s szíve
önkénytelenűl gyúl szerelemre a deli vadász iránt. Nyugalma,
boldogsága, élete úgy száll el, mint megrezzent kezéről, első
találkozásukkor, a pillangó. Hallgatag érzésében, szerény és
homályos vágyódásában, néma merengésében mi vétséget sem
követ el: a világtörvény teljesedik rajta. Abból a természeti
kényszerből, mely elhervasztja a liliomokat, folyik az ő liliomhullása
is. A báj eltűnésének e képe mellé sorakozik a boldogság, fény és
hatalom mulandóságának az a példája, melyet Kemény Zsigmond
alkotott Csiaffer basában, a Két boldog egyikében. Hatalom és
boldogság övezik budai palotájában: urának kegye, kincsek
sokasága, szivek szeretete s lelkének nyugodalma. Mindez
megérdemelt: Csiaffer istenfélő, vitéz, igazságos és szerető szívű.
Minden ok, minden kihívás nélkül érkezik meg hozzá egyszerre a
szultán halálos itélete, s a «boldog», Allah akaratában, a
világtörvény érvényesűlésében való fenséges megnyugvással siet
veszte elé.
A világtörvény tragikuma az, a mit a görögök az istenek
irígységére, a fthónoszra, vezettek vissza. Az élet szépségéből
fakadó világnézletök derűjébe sötét árnyat vetettek a természeti
kényszernek bús és megrázó jelenetei. Kétszeres fájdalommal
látták, mint húll el a jó, a szép, az erős a hitványak mellől. Ezt a
keservet erőteljesen fejezi ki Philoktetesnek egy kifakadása. A trójai
hősök sorsa felől kérdezősködik Neoptolemostól s megérti, hogy
Achilles, Ajas, Antilochos és Patroklus már mind meghaltak. A
legnagyobbat magának Phoibosnak nyila terítette le; a többiek is az
isteni végzésnek lettek áldozatai. De Diomedes és Odysseus, kik a
nyomorúltat a puszta szigetre kitették, még élnek, s él a veszekedő
Thersites is. Erre a hírre fakad ki a beteg hős:

Úgy is kell. Hisz még nem veszett el semmi rossz


Jól gondoskodnak erről a nagy istenek,
Kik gyakran visszahozzák Hades karjai
Közül is mindazt, a mi csalfa és gonosz,
És mindig sírba döntik azt, ki jó s igaz.
Mit mondjak erről, mint dicsérjem ezt, holott
Az istenekben is gonoszságot lelek?

Az isteneknek e gonoszsága abban az irígy félelemben áll, hogy


valamelyik halandó kiválóságában hozzájok emelkednék. A mint
Homér magyarázza: az emberek háborítatlan boldogságukban
elfelednének föltekinteni az istenekhez, s ők tisztelet és áldozatok
hijával maradnának.
E felfogás az istenek irígységéről az emberi kiválóságra, a görög
szellem különböző nyilatkozataiból egyenlő erővel sugárzik ki.
Megleljük az életbölcseségnek leggyakrabban hangoztatott
tételében, mely mindenek fölött mérsékletre, tartózkodásra,
óvatosságra int; a költők tragikai eszméiben, melyek a természeti
kényszer hatalmát példázzák; sőt a történetírók képzetében is a
világesemények uralkodó törvényéről. Herodot több helyen is kifejti
bővebben: Solon intésében, melyet a boldogságával dicsekvő
Krőzushoz intéz, Artabanus beszédében, melylyel Xerxest a scithák
és görögök ellen indítandó háborútól visszatartani kivánja s Amasis
tanácsában, melylyel a túlboldog Polykratest arra inti, hogy a
leskelődő balsors kiengesztelésére dobja el magától legdrágábbnak
tartott kincsét. Geréb József gondosan állította össze egy
értekezésben Herodotnak ide vonatkozó nyilatkozatait. El van
ezekben mondva, minő irígy és ingatag az istenség. Sokakkal
megízlelteti a szerencsét s aztán romlásba taszítja őket. A kiválókat
villámával sújtja s nem engedi fenyleni, míg a kicsinyek nem ingerlik
maguk ellen. Mindig a legnagyobb épületekre s a legmagasabb fákra
röpíti gyújtó nyilát, mert meg szokta csonkítani mindazt, a mi
felmagaslik. Hányszor győz le valamely kis sereg egy nagyobbat, ha
az isten irígységből rémületet vagy mennykövet küld rá; nem tűri a
földön senki másnak fenhéjázását mint a magáét. Azért a tulságos
szerencse mindig veszedelmes, mert magára vonja az istenség
haragját. Minél magasabbra emelkedik valaki, annál mélyebb bukás
várja s annál bizonyosabban. Az az igazán boldog, kinek életében a
sors szerény kedvezéseit enyhe csapásai váltogatják. Boldog az is,
kit a nagy öröm után azonnal sújt halála, mert meg lesz kimélve
legalább a visszaeséstől; ezért nevezi Solon oly boldogoknak
Kleobist és Bitont, mivel akkor haltak meg, mikor mindenki dicsérte
és csodálta őket. A népek és hősök, országok és királyok nagyságát
is, mely a természet törvényei szerint növekedett, a romlásnak
hasonlóan természeti s kikerűlhetetlen törvénye fenyegeti. Ebből a
felfogásból, melyet Hegel, vallásfilozófiájában, egyensúlyozásnak
nevez, bár a természeti kényszer érzete benne az uralkodó tényező,
kiérzik némileg az erkölcsinek az a fejletlen csirája, melyet Vischer
említ.
A nagy szerencsétől az elbizakodásig, a fenhéjázásig csak egy
lépés van; egy röpke gondolat már sértővé teheti azt, a mi még csak
fenyegető. A hübrisz alapja, föltételei megvannak benne, az isteni
irígység annak veszi elejét. A Herodot által elbeszélt két, ide vágó
monda hősei: a boldog Krőzus és a szerencsés Polykrates, még
nem tették meg ezt a lépést s a tárgyaltuk körön egészen belül
maradnak. Erejök nem csapott hübriszbe, s a csapások, melyek
amazt kedves fiának halálával, ezt meg a jóniai haddal sújtani
kezdik, nem az erkölcsi, hanem a természeti törvény érvényesűlései.
Ez azonban amazt is védelmezi, midőn oly támadásoknak veszi
elejét, melyek a lesújtott kiválóság részéről könnyen és mihamarabb
az erkölcsi ellen intéztetnének. Ekként érvényesűl az egyetemes
fogalma már magában a természeti törvényben, ennek legszélső
egyoldalúságában is. Említettük már, hogy eszméje a művészetben
is nyilatkozik. A szerencsének gyors változásai, a hirtelen csapások
és megfélemlítő fordulatok jeleneteivel sűrűn találkozunk a görög
tragikus költőknél. Sokszor felismerhetjük bennök az egyoldalú,
eredeti természeti nézlet nyomát, mely azonban hovatovább
mindinkább enged az erkölcsi felfogásnak.
Van-e ennek az eredeti antik felfogásnak valami nyoma a mi
antikizáló költészetünkben? Tudjuk, hogy az az egész harcz, mely
költőinket a múlt századi újjászületés után különböző zászlók alá
gyűjtötte s egymással szembe állította, inkább a formára, nyelvre,
verselésre, mint a lényegre vonatkozott. Klassziczistáink is inkább az
antik formáknak mint az antik szellemnek hódoltak, s inkább a római
mint a görög költők tanítványai. Különösen az ó-klasszikai iskola
megalapítói, Baróti Szabó, Rajnis és Révai. Nagyobb utódaiknál,
Virágnál és Berzsenyinél, már inkább érezzük a klasszikai szellem
ihletét. Mindegyiköknél találunk, bár csak elvétve, hangokra,
fordulatokra, kifejezésekre, melyek a görög felfogás viszhangjainak
tetszenek a természeti törvény kérlelhetetlen uralkodásáról. A
lelkesítő ódák mellett, melyek a fel-fellobbanó nemzeti tüzet élesztik,
az újra meg újra beköszöntő sötétségben, a csalódás és csüggedés
óráiban amaz örök erős törvénynyel magyarázzák a hanyatlás képét
s készítik elő a szellemeket a fenyegető végső csapásra. Míg ennek
gondolata rettegteti őket, a virágzást követő hervadásnak, az
emelkedést felváltó sülyedésnek, a fényt elnyelő homálynak
általános, természeti szükségszerűségében keresnek némi elegiai
megnyugvást. Virág, megáldván a hajót, melyben hazáját példázza,
hogy a tenger háborgása között viseljenek rá gondot az egek, így
folytatja:

Mégis rettegek én. Nincsen az ég alatt


Állandó dolog: a nap hamar elborúl:
Jön egy fergeteg, a mely
Ránk bút mennydörög és halált.

A Vigasztalóban még élesebb kifejezésre jut e komor gondolat. A


költemény abból a hangulatból fakad, mely oly kiváló szerepet játszik
az egész antik költészetben: megnyugvást keresve a
változhatatlanban, a fenyegető és igaztalan esetlegben, önként tör ki
belőle a keserű szemrehányás a végzet ellen. A pokol bú-gond vele
evez a hajóssal s követi a lovagdandárt, sebesebben mint a szarvas
s a felhőt rohanva üző fergeteg. Mi marad számunkra, a vak
megnyugvásnál egyéb, e világon, mikor látjuk

Hires Achilles mi hamartan elhalt!


A vajudt Tithon mi soká nyavalygott!

Nem ez a feljajdulás volt-e az, melyben Philoktetes tört ki, mikor


Neoptolemostól meghallotta, hogy Achilles elesett, de Thersites még
él. Berzsenyi hatalmas ódája, a Magyarokhoz, ugyane felfogásnak
viseli bélyegét. Lelkesedését és haragját, az elkorcsosúlt s vesztébe
rohanó nemzedék ellen, az erkölcsi eszméből meríti. A tiszta
erkölcs, mely minden ország támasza, talpköve, megveszvén,
érdemlett romlásba ragadja a magához hűtelenné lett nemzetet. De
a nyitott sír előtt, melyet a költő képzelete fest, elhallgat a vád;
fenséges felháborodását mintegy elcsitítja fájdalma a közelgő
pusztuláson. Lelke elfordúl a haragra zaklató októl: a kibékítő
megnyugvást keresi. Egy csodaszép fordulattal a világtörvényre
hivatkozik:

De jaj, csak így jár minden az ég alatt!


Forgó viszontság járma alatt nyögünk.
Tündér szerencsénk kénye hány vet,
Játszva emel s mosolyogva ver le.
Felforgat a nagy századok érczkeze
Mindent: ledült már a nemes Ilion,
A büszke Karthago hatalma,
Róma s erős Babylon leomlott.

E fenséges föllendűléssel a magyar költő föléje emelkedik


példányának, Horatius Ad romanos czímű ódájának, melynek
hatása alatt írta versét. Ebben is a múlt ereje van szembeállítva a
sűlyedt jelennel; de a római lantos megtalálja a kiengesztelést a
nagy istenek szent romjainak s koromtól undok szobrainak
kijavításában. Berzsenyi hatalmas ódájával rokon egy másik
költeményének, a Temetőnek alapgondolata. A porszemek, melyek
egykor éltek, örűltek és szerettek, hatalmasabb képzetekre izgatják
a költő lelkét. Az elszórt kődarabokról Persepolis és Palmyra képe
int felé; Theba kevély tornyait s a márvány Babylon falát látja
leomlani. Az egyetemes elmúlás világtörvényének fogalmához
emelkedik:

Látom hangyabolyi míveidet, világ!


Mint szórja s temeti a nagy Örök keze.

Ha az erősön és gyöngén egyként erőszakoskodó végzetet, a


halált általában, nem találhatjuk is tragikusnak, nem, például, mikor
jelentéktelen áldozatokat ragadván el, nem ébreszti föl bennünk a
végetlen, legyőzhetetlen hatalom képzetét: tragikai benyomás
tényezőjeül mutatkozik mindig, mikor valamely kiváló erőt semmisít
meg. Szépség, gazdagság, hatalom: mind erőt képviselnek, s a
régiek felfogása szerint a szerencse is fenségi elem: Brutus,
gyászbeszédében, Cæsarnak szerencséjét is magasztalja. Midőn a
halál az erőset győzi le, annál tragikaibb hatású, minél nagyobbnak
mutatja bukásában a nagyot. Zeising hasonlata: «mint a király ütése
lovaggá avatja a harczost, úgy a sors csapása hőssé emeli az
embert». De a küzdő erők képzete kölcsönösen emelkedik egymás
által. Ha a nagyra dicsőség csak a végetlen által győzethetnie le,
ennek benyomása is megrázóbb lesz áldozatának nagysága által. A
halál, mely így a kiválasztottat a kiválóság színében mutatja, mintegy
felmagasztalja, maga sem tünhetik föl annak a ravasz és kicsinyes
ellenségnek, ki csak meglepés, árulás, cselvetés által képes diadalt
aratni. Csak mikor egész erejével, teljes hatalmában áll előttünk,
csak akkor érezzük benne Schiller gigászi sorsát, mely az embert
fölemeli, mikor eltiporja. Minél nagyobb erőt győz le, minél inkább
megfeszíteni látszik minden erejét, hogy győzhessen, annál
nagyobbnak, mintegy hősiesebbnek fog feltűnni maga is. A szemben
álló erőknek egymás által emelkedő képe, Cæsarnak egy napon
született két oroszlánja.
Hogy az emberi szellem mint alkotja meg az ismeretlen képét,
ennek az ismerthez való viszonyából, a halálét prédájából:
tanúlságos példáit láthatjuk ama különböző ábrázolatokban,
melyekkel a művészi képzelet a halált kifejezni törekedett. Fogalmát
érzéki alakba kellett öltöztetnie; ez érzéki alaknak fő tulajdonságul
erőt mutatnia; ez az erő határoz az alak felett. Az erő azonban,
melynek képzetét a halál különböző esetben felébreszti, különböző.
A magabiró férfit erőszakkal veri le, az aggastyánt csak kézen fogva
vezeti sirjába. A műszellem már annak az erőnek keresett megfelelő
alakokat, mely a halál különböző áldozatainak elejtésére
szükségesnek mutatkozik: módosítva, változtatva úgy szólván ezek
által s ezekhez képest. Ha nem találunk is e haláltipusokban mindig
világos következetességet, tudatos törekvést, határozott rendszert:
de fellelhetjük kétségtelen nyomait annak a felfogásnak, melyre
utaltunk, s e nyomokban egyszersmind tételünk bizonyságait. A
hadisten, Ares, kiséretében megjelennek a csatatereken a Kérek, az
erős, harczos férfiak erőszakos, véres halálának istennői.
Milyeneknek képzelték ezeket a görög költők, különösen Hesiod;
milyeneknek faragták mestereik az ékes hadi szerszámokra,
fegyverekre, paizsokra s festették vázáikra? Iszonyú, sötét,
ellenállhatatlan erejű alakoknak, vadállatok fogaival és karmaival
vérvörös öltözetben, kegyetlen vérszomjjal vicsorítva fogaikat, az
elesteket és sebesűlteket hurczolva magukkal. Tőlük mennyire
különböző, mily egészen más alakban mutatják a halál géniuszait a
xanthosi hárpia-emlék híres domborművei, melyek a görög
szobrászatnak legnemesebb kezdetei közé tartoznak. A másnemű
halált: gyermekekét vagy talán azokét a jámborokét, kik a
szomszédos képeken áldozatokkal járúlnak az istenek elé. Két,
egymásnak megfelelő táblán látjuk a hárpiákat, női felső testtel,
kiterjesztett szárnyakkal, madárlábakkal és farkkal. Két gyermek-
alakot visznek ép tova. Mozdulatuk erőteljessége mellett is könnyed:
mintha csak lebegnének, de feltarthatatlan erővel; alakjokban,
kifejezésökben semmi rémletes. Overbeck is megjegyzi, hogy «e
komoly, szelíd lények, kik az elköltözötteket keblökre szorítják, mig
ezek is odaadólag nyújtják feléjök karjaikat: mennyire különböznek
ama kegyetlen és ragadozó alakoktól, a homéri költészet hárpiáitól,
kiknek hatalmát karmaik és roppant szárnyaik jelölik.» Ezeken kívül
a klasszikai népeknek még különböző tipusaik voltak a halálra.
Euripides Alkestisében fellépteti magát Thanatost, a halált saját
személyében, feketébe öltözve, fekete szárnyakkal s késsel,
melylyel a halónak egy fürtjét vágta le áldozatul az alvilág isteneinek.
Megjelenik a halál gyakran az álom, Hypnos, oldalán, kinek
ikertestvére, egy szép ifjú vagy fiú alakjában, szárnyasan vagy
szárnyatlanúl, kezében aláfordított, lobogó fáklyát tartva. Az élettől
vett szelid búcsú, könnyű távozás jelképe, a hogyan a régiek
általánosságban a halált tekinteni szokták. Hogy e különböző képek
alkalmazásában, vonatkoztatásában mily kiterjedésű és fokú
következetesség nyilatkozik: e kérdés szorosabb és behatóbb
vizsgálata nem lenne hálátlan feladat a régiségbuvárlatra.
Annak a megkülönböztető felfogásnak némi nyomát, melyet
érintettünk, megtaláljuk a középkor egyik leghatalmasabb és
legmegragadóbb műemlékén is, a pisai Camposantonak
tizennegyedik századbeli nagy freskóján, a Trionfo della Mortén. A
föld urai, a hatalmasok és élvezők, életök kárhozatos vetése után,
lekaszabolva feküsznek egy halomban a középen: királyok és
királynék, lovagok és polgárok, papok és apáczák. Mind olyanok,
kiknek okuk volt ragaszkodni az élethez s küzködni a halál ellen,
mely a pokol kapuját nyitotta meg előttük. Legyőzte őket hatalmuk,
gazdagságuk, díszeik és képmutatásuk daczára. Iszonyú alakban
lebeg felettök. Egy rémletes nő-óriás, denevérszárnyakkal és
karmokkal, dühtől szikrázó szemekkel és éhesen tátott szájjal;
felbomlott hosszú haja és sötét ruhája vadul lebegnek; kezében a
gyilkos kasza. Komor, borzalmas fenségében igazi michelangeloi
alak. A levegőben ellenállhatatlanul száguldani látszik. Miután a
gonoszokon elvégezte dolgát, a boldog és jámbor nyugalomban élők
kerti csoportja felé tart. A szív békéjében pihenve gránátalmafák
alatt elmélkednek, beszélgetnek, zenélnek ezek. Rájok nézve, kik
győztesek a bűnön s a kiknek nincs okuk küzdeni a halál ellen,
egészen más ennek a képzete. Felettök szállong a két halál-géniusz:
kecses angyal-alakok, egyik kezökben nyillal, a másikban felfordított,
égő fáklyával. A műtörténetírók vitatkoznak fölötte, hogy nem
valamely későbbi javító adta-e e jelvényeket kezökbe s változtatta át
őket, kik eredetileg egyszerűen angyaloknak voltak festve, a halál
képviselőivé. Ránk nézve a vita eredménye nem fontos. Annyit
mindenesetre bizonyítva láthatunk, hogy egy művész képzelete,
akár magáé a mesteré, akár a javítóé, más-más áldozatokkal
szemben más-más alakban ábrázolta a halált. A nagyok, gonoszok,
ellenállók leverője ama félelmes megéra, a jóké és békéseké a
nyilas angyal. Még a Holbein-féle Haláltánczból is meríthetünk némi
tanúlságot. Itt már a halál az ismeretes csont-ember. De nem merő
váz; soványsága mellett is látszik rajta, hogy rendkívüli erőkifejtésre
képes. Hogy mily iszonyú erővel ragadja meg áldozatát, talán
legszembetünőbben példázza a kép, melyen a vonakodó barátot
hurczolja magával. Erejét ki is fejti mindenütt, a hol szükség van rá:
mikor a lovagnak fejéhez csapja paizsát s a másikat kopjával szúrja
keresztül; mikor a vérszomjas katonát, elejtett ellenségének holtteste
fölött, egy lábszárcsonttal veri le; mikor a rablónak mint dühös
oroszlán mutatja meg, hogy ki az országút igazi ura; mikor a tengeri
vész által hányt hajót a mélybe ragadja. Csalfa az együgyűekkel és
hiszékenyekkel, de erős az erősekkel szemben. Kugler ellenében,
ki e képeken a halált mindenütt egyenlőnek, mindig ugyanannak az
alattomos és kárörvendő démonnak látja s folyton a lélekzet-szorító
es-moll dallamot hallja: helyesen mutogatja Ilg Albert, hogy az
életnek más-más viszonyaiban más és más módon lép fel a halál.
Alig teszünk egyebet, mint e gondolatot fejezzük ki, midőn más-más
alakot mondunk. Méltán kereshetjük nemcsak azt, hogy miképen lép
föl a halál az erejök által megkülönböztetett élők ellen, hanem azt is,
hogy minő halál lép föl. A művész humora e rajzokban, az erőszakos
halál borzalmas képeiben szinte páthoszba megy át s a tragikumot
érinti. Egészen ennek a magaslatán száguldanak Dürer és
Cornelius apokalypsisi lovagjai, e félelmes, hatalmas és hősi
alakok, melyek kaszájokkal, pallosukkal és nyilaikkal a természeti
törvény betelését példázzák az egész emberiségen. Azt a hatalmat,
mely erősebb az emberiség összesített erejénél. Háttérben tartja
egyikök a mérleget: a természeti törvényt mintegy nyomon kíséri az
erkölcsi szentesítés…
Ámde vegyük föl az elejtett fonalat. A sors leskelődő és
alattomos hatalom, mely a földi nyugalmat és jólétet folytonosan
fenyegeti, s kihívás nélkül is, váratlan és véletlen csapások által
reátör: ez a képzet mindenütt él az emberi lélekben s a világ
folyásának szemléletéből szakadatlanul új meg új táplálékot merít.
Természetesen annál erősebb és mélyebb, minél kevesebb ismeret,
minél felületesebb felfogás, minél szűkebb látókör az, mely a
természet rendjét s általában az anyagi és erkölcsi világ tényeit,
összeköttetését tekinti. Minél fogyatékosabb a tapasztalásunk, annál
több jelenségben fog megrendíteni bennünket a dolgok olyan
titokteljes és mélyebb összefüggésének sejtelme, mely a tapasztalat
körén kívül esőnek látszik. Magától értetik, hogy minél kisebb ez a
kör, annál több minden marad kívül rajta. Előitéletekben,
ráolvasásokban, babonákban mind annak a rejtelmes kapcsolatnak
sejtése nyilatkozik. Ezen alapszik a csillagjóslás egész elmélete,
melynek egy töredékét öltöztette Tompa Futó csillaga költői képbe.
Wallenstein leánya, Tekla, a csillagvizsgáló toronyban vigasztalást
merít a gondolatból, hogy:

Az égnek mérhetetlen boltivén


A szeretetnek koszorúja már
Megfonva rég tündöklő csillagokból,
Korábban, mint életre ébredénk.

Ebben az eszmekörben mozognak azok a műalkotások: mesék,


mondák, balladák, drámák is, melyek babonás hitre támaszkodnak,
vagy legalább indítékul használják föl azt s czélzatukkal rá
hivatkoznak. A természeti és erkölcsi világ nem értett kapcsolatát
egyszerűen elfogadják nem is érthetőnek, s erkölcsi vétségek
visszahatásául a merő vakesetet. A babona szerint valamely új
épület tartósságát csak egy beléje falazott áldozat biztosíthatja. A
Déva várát rakó tizenkét kőmives is haszontalanul dolgozik: a kit
éjjel raktak, az nappal leomlott; a kit nappal raktak, az éjjel leomlott.
Kőmives Kelemen erre azt a törvényt teszi, hogy a melyikök felesége
hamarább kihozza az ebéd vékáját, kő közé rakassék s ott
megégettessék. A sors az ő feleségét éri, mint a rokon tárgyú, oláh
árgesi zárdában Manoliét, s a görög artai hídban az első mesterét. A
monda maga a vaksorsnak babonás felfogásából fakadt, hogy a
népszellem mint vetett ebbe erkölcsi magot, mikor mindenütt
magukat a javaslókat sújtja: arra rámutat Greguss a ballada
elméletében. Ama babonás nézlet természetét élénken megvilágítja
azoknak a mondáknak legnagyobb része, melyek valamely
megfogant átok alapján fejlesztik cselekvényöket. A mű- és
népköltésben nem egyszer találkozunk viselős asszonyokra mondott
átkokkal. A mi az idő méhében rejlik, a balsors, titokteljes módon
megy teljesedésbe az által, kit a megátkozott anya méhe hord.
Merényi közöl sajóvölgyi gyűjteményében egy népmesét: a szegény
ember kicsúfol benne egy koldúsasszonyt, kinek hármas
ikergyermeke van s otthon az alatt az ő felesége kilenczet szül. A
Miczbán-mondában, melyből Mészáros Ignácz novellát, Szigligeti
pedig drámát írt, s a melyet mellékesen Katona is felhasznál Bánk
bánjában, maga a bánné a csúfolkodó, kit egyszerre hét gyermekkel
tesz csúffá a végzet. Müllner Vétek súlyában is Don Valeros
házanépén az az átok teljesedik s vezeti az egész drámai fejlődést,
melyet egy megbántott koldúsasszony mondott terhes feleségére.
Mindenütt látunk bizonyos erkölcsi magot; de a visszahatás
módjában, az egyetemes érvényesűlésében mégis csak valamely
titokteljes és megfoghatatlan természeti hatalommal állunk
szemközt, mely nem tetteinknek és sorsunknak okozatos
lánczolatában, hanem merő esetlegképen nyilatkozik. Nem annyira
megbántott vagy akár féltékeny ellenfelünknek, mint inkább
kibékíthetetlen, örök ellenségünknek látszik.
E felfogás az alapmotivumuk az úgynevezett sorstragédiáknak. A
vakságában kiismerhetetlen végzet uralkodik bennök, melynek még
következetessége is csupa véletlenség. Az egész irány, mely
századunk első negyedében főként a németeknél jutott rövid életű
virágzásra, Schiller Messinai arájára támaszkodik. A fejedelmi ház
két ifjú sarja küzd meg benne életre-halálra, s juttatja egymást
gyászos végre a leányért, kiben végűl édes testvéröket ismerik meg.
Mindez meg volt jósolva álomlátásokban még Beatrice születése
előtt s a képletes jósálmok be is telnek. E végzetes történet azonban
az antik tragikai eszmének hasonlíthatatlanul mélyebb és tisztább
felfogását érezteti, mint a későbbiek. A messinai fejedelmi háznak
igazi, megengesztelhetetlen átkát vad, daczos, hatalmaskodó
jelleme képezi. Ez a jellem, melynek többé-kevésbbé osztályosa
minden tagja a családnak, idézi a végzetet fejére s mutatja, saját
hősisége által, megrázó hatalmúnak. Az álmok és hüvelyezéseik, a
görög értelemben vett fátum egész szerepe inkább csak az, hogy e
tragikai eszme hatását támogassa. Nem így a tulajdonképeni
sorstragédiákban, melyek nem is követték azonnal nyomon a
Messinai arát. Minor, ez iskola derék történetírója, igen helyesen
mutat rá a külső okokra, melyek felburjánzását elősegítették. A
súlyos csapásoknak egész sora s legkülönbözőbb nemei készítették
Németországon a szellemeket a sorsnak olyatén felfogására, minőn
e szinművek alapúlnak. A kormányok zsarnoki nyomása nehezűlt a
nemzetre, melyet még háborúk, inségek és ragályok sújtottak; élet,
vagyon és hatalom csak játéknak látszottak a végzet kezében; a
hősök és gonosztevők sorsa számtalan esetben egy és ugyanaz
volt. Ime a sorstragédiák komor előjátéka, mely hatásukat
előkészítette. E hatás alapja jórészt a közviszonyokban rejlik,
melyeknek változása csakhamar el is temette az egész irányt.
Méltán. A Február huszonnegyedike Wernertől, a Világitótorony
Houwaldtól, a nálunk is ismert Vétek súlya Müllnertől és mind a
többiek csak a rejtelmes, a nyomasztó, a megfélemlítő hatására
törekszenek. Ezt a megfélemlítőt pedig nem tetteink bérének
kikerűlhetetlenségébe, hanem a tett és szenvedés közötti okozatos
összefüggés fölismerhetetlenségébe helyezik. Nyomorúlt áldozatait
nálok bábként dobálja a végzet, váratlanul és esetleg csap reájok s
maga is, mintegy tolvajként lopózván be a kiszemelt házakba s
rejtőzködvén ott, hogy alkalmas pillanatban előronthasson, egészen
kivetkőzik fenségi szinéből. A költő is mintha reszketne előtte s nem
merne szemébe nézni: kisérletet sem tesz rá, hogy megismerje. A
kinek ép az lenne a feladata, hogy megáldott szemeivel behasson a
dolgok benső alapjába és összefüggésébe; tisztán lássa és láttassa
a vétségnek és megtorlásnak, a mértéktelenségnek és bukásnak, az
egyetemes kihivatásának és visszahatásának világos kapcsolatát:
művészete fő elvévé e kapcsolat eltitkolását emeli. Maga hirdeti,
hogy: e földön csak a történeteket láthatjuk, okaikra az itélet napjáig
kell várakoznunk. Mennyire hiányzik minden fölemelő s még
megnyugtató elem is e fölfogásból! Midőn a bűnt sújtja, nem a
bűnhödésnek ebből fakadó erejével és kérlelhetetlenségével, hanem
titokteljes, megfoghatatlan módjával akar hatni. A benyomás mindig
homályos marad, hogy vajjon a szenvedés: megtorlás-e igazán,
vagy pedig véletlen szerencsétlenség. Ha van is erkölcsi eszméje,
hatását sohasem ebből fejleszti, nem ennek érvényesítésében
keresi, hanem a vaksors, a merő természeti kényszer
félelmességének példázásában. Az egyetemes, a mint itt elénk van
állítva, borzalmas és oktalan szeszélyében csak Gloster keserű
kifakadására emlékeztet:

Hallám régebben, hogy mik a legyek


A pajkos gyermekeknek, az vagyunk
Az isteneknek mink: mulatkozásból
Öldösnek el bennünket.

Nem látunk-e rokonságot e felfogás s az új franczia naturalizmus


irányelve között? Az egyetemes nála is mint rideg természeti
kényszer nyilatkozik, mely eleve arra szánja s már akként alkotja
meg áldozatait, hogy minél biztosabb prédáivá legyenek. Mindent
pusztán fizikai okokra alapít, öröklött szervezeti tulajdonságokra, a
vérmérséklet változhatatlan érvényesűlésére; ezen kívül rá nézve
nem létezik semmi. Az embert sohasem látjuk, még nyomaiban sem,
úgy, a mint maga alkotja magát, hanem csak a mint a természet
kikészítette vak erejének játéklapdájaul. A rabszolgatartó mindenütt
ugyanaz; csakhogy amott sorsnak hívják, itt meg természetnek.
A sorstragédiáknak nem volt erősebb hatásuk a magyar
költészetre. Divatjuk ép abba az időbe esik, melylyel nemzeti
föllendülésünk megindúl s a nemzeti akarat erejébe vetett bizalom
ébredezni kezd. E szellem kétségkívül ép oly kedvezetlen volt
eszméikre, mint a mily kedvező a német közviszonyok talaja. De
némi viszhangot mégis ébresztettek. A felfogásnak, mely bennök
nyilatkozik, némi elszórt nyomaira legalább akadhatunk. Kisfaludy
Sándor regéinek egy része, mint különösen Csobáncz és a
Szentmihályhegyi remete, a vétlen erény bukását példázza, mintegy
a világtörvény tragikumát. A boldogságunkra leskelődő, félreértések
és esetlegek által romboló, kiismerhetetlen módon büntető végzettel
is találkozunk ez egykor oly népszerű költeményekben. Egyikök a
Miczbán-mondát adja elő. Csobáncz boldogságát «a sors mérge»
dúlja föl: a harczból megtérő várúr megöli ártatlan nejét, kit
ismeretlen testvérével találván együtt, hűtlennek hisz; közel
rokonságban van vele Vörösmarty Széplakának tárgya. De a
sorstragédiák ismert mechanizmusából is találunk Kisfaludy
regéiben egyetmást. Tátikában Pongrácz hajdú, mikor karácsony
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