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

Domain Specific Languages in R Advanced Statistical Programming 1st Edition Thomas Mailund all chapter instant download

Advanced

Uploaded by

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

Domain Specific Languages in R Advanced Statistical Programming 1st Edition Thomas Mailund all chapter instant download

Advanced

Uploaded by

khathboornri
Copyright
© © All Rights Reserved
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/

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
Thomas Mailund

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

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
.

ISBN 978-1-4842-3587-4 e-ISBN 978-1-4842-3588-1


https://doi.org/10.1007/978-1-4842-3588-1

Library of Congress Control Number: 2018947391

© Thomas Mailund 2018

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.

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.
Table of Contents
Chapter 1:​Introduction

Who This Book Is For

Domain-Specific Languages

Chapter 2:​Matrix Expressions

Parsing Expressions

Meta-Programming Parsing

Expression Manipulation

Optimizing Multiplication

Expression Rewriting

Expression Evaluation

Chapter 3:​Components of a Programming Language

Text, Tokens, Grammars, and Semantics

Specifying a Grammar

Designing Semantics

Chapter 4:​Functions, Classes, and Operators

The S3 Object-Oriented Programming System

Objects and Classes

Generic Functions
Operator Overloading

Group Generics

Precedence and Evaluation Order

Code Blocks

Chapter 5:​Parsing and Manipulating Expressions

Quoting and Evaluating

Exploring Expressions

Manipulating Expressions

Chapter 6:​Lambda Expressions

Anonymous functions

Experiments with Alternatives to the Syntax

Don’t Do This at Home

Chapter 7:​Environments and Expressions

Scopes and Environments

Default Parameters, Lazy Evaluation, and Promises

Quotes and Non-standard Evaluation

Chapter 8:​Tidy Evaluation

Quosures

Quasi-quoting

Chapter 9:​List Comprehension


Chapter 10:​Continuous-Time Markov Chains

Constructing the Markov Chain

Constructing a Rate Matrix

Traces

Computing Likelihoods

Chapter 11:​Pattern Matching

Constructors

Pattern Matching

Lists

Search Trees

Chapter 12:​Dynamic Programming

Parsing Expressions

Evaluating Expressions

Fixing the Evaluation Environment

Chapter 13:​Conclusion

References

Index
About the Author and About the
Technical Reviewer
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.

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 .
© Thomas Mailund 2018
Thomas Mailund, Domain-Specific Languages in R, https://doi.org/10.1007/978-1-
4842-3588-1_1

1. Introduction
Thomas Mailund1
(1) Aarhus N, Staden København, Denmark

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 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.

Domain-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, 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.
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")

## 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.
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"))
}
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")

## 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.
© Thomas Mailund 2018
Thomas Mailund, Domain-Specific Languages in R, https://doi.org/10.1007/978-1-
4842-3588-1_2

2. Matrix Expressions
Thomas Mailund1
(1) Aarhus N, Staden København, Denmark

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.

In this chapter, we use the following library:

library(microbenchmark)

Parsing 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) {
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, ...) {
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])

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.

Meta-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]
])))
}
}
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)
}

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])

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
}
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.
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 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 × … ×
A n . We need to set parentheses somewhere, say (A1 × A2 × …A i )
× (Ai+1…× A n ), 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 × …A i ) are n × k and the
dimensions of (Ai+1…× A n ) 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 A i ,Ai+1,…,A j can be computed recursively as Ni,j =
0 when i = j and
Random documents with unrelated
content Scribd suggests to you:
respect of each person so employed, must be entered immediately
on commencement of work in the process named.
Various methods of noting the state of health of the workers have
been adopted. Use of the words “Good,” “Very fair,” and “Fair,” is
common as indicating the state of general health, with special note in
addition, often in the form of a symbol, of the presence and character
of definite ill-effects. The object of the register, however, is to keep a
record intelligible not only to the Certifying Surgeon, Factory
Inspector, and occupier, but also to the workers. Entries, therefore,
on a uniform system are desirable, taking account of the two aspects
of the health of every lead-worker, which must be considered (a) that
indicative of specific effects from the occupation, and (b) that of
general health uninfluenced by the employment. With this in mind,
the following system of entry in the health register has been adopted:
The entries should be made upon a uniform system, as below, indicating
degrees of deviation from normal health, and distinguishing (by use of numerals)
those attributable (or possibly attributable, in whole or part) to work in lead, from
those not so attributable, for which latter letters should be used. The conclusion is
1 2
perhaps best expressed as a fraction , , and so on.
A C
The numerals should be taken to mean:
1. Passed without comment (no observed effect of lead).
2. Blue line (or indication thereof).
3. Marked (quasi-pathognomonic) anæmia, or other signs of impairment of
health. (Albuminuria, or slight deficiency in tone of the extensor
muscles of the forearm, would, and miscarriage, or other suspicious
history of illness between examinations, might, come under this head.)
4. Suspension or transfer, by reason of impairment of health from effects of
work in lead. (In such cases the surgeon would be prepared to
entertain an application for a certificate under the Workmen’s
Compensation Act.)
Except in the case of a worker whose exposure to lead is only recent, renal
disease should always be indicated by a numeral.
Letters should bear the following meaning:
a. No comment (i.e., fair general health).
b., c. Increasing degrees of impairment of general health. (Pregnancy, if
without suspension, should be entered as c.)
d. Suspension or transfer, for reasons other than impairment of health from
effects of work in lead.
x. Carelessness, or neglect of precautions, or unsuitability for work in lead.
(Suspensions for such reasons should be marked dx.)
Such entries of numerals and letters will in general suffice for the intended
purpose; but the surgeon may, of course, find it desirable to make other notes for
his own information, and it is within his discretion to supply further details to
occupiers or workers concerned.

REFERENCES.
[1], [2] S. King Alcock, B. M. Bond, A. Scott, and others, in discussion on
the Value of Systematic Examination of Workers in Dangerous Trades. Brit.
Med. Journ., vol. ii., pp. 741-749, 1902.
[3] King Alcock: The Early Diagnosis of Industrial Lead Poisoning. Paper
contributed to the Second International Congress for the Study of Industrial
Diseases held at Brussels, 1910.
CHAPTER XIV
PREVENTIVE MEASURES AGAINST LEAD
POISONING—Continued

Overalls and Head Coverings.—Stress has been laid on the


wearing of overalls and head coverings in processes giving rise to
dust or to splashes of glaze or paint in special rules and regulations
in the past. With the improvement that has taken place in exhaust
ventilation, they have become less important. Indeed, the aim of all
manufacturers and ventilating engineers should be to render
processes so free of dust as to make them altogether unnecessary.
Increasing knowledge of the insidious manner in which lead dust can
arise has shown that from this point of view overalls of the cotton or
linen material ordinarily worn constitute a real source of danger.
Splashes of glaze dry on them, and at every movement involving
rubbing of the surface dust is generated. Some operations almost
oblige the worker to press the article worked upon against the chest,
so that chance of inhalation of dust from this source alone is
considerable. Taking them off creates dust, and after this is done a
reprehensible practice exists of either shaking or beating them
against a post. In large factories they are usually washed on the
premises, and the water in which this is done will become a solution
containing some lead in suspension. Hence, even when washed and
dried ready for wear, overalls may not be quite free of lead. Apart
from the general obligation recognized that an employer should
provide and maintain everything necessary to guard against danger
contracted in his factory, we think that the risk run by a worker in
taking the overall home and washing it there is negligible, and offers
advantages in the ultimate cleanliness of the overall over washing on
factory premises. Laundresses shaking overalls prior to washing
them have been known to contract plumbism.
Where work with the arms is incessant, as in the heading of yarn,
overalls are burdensome, and for this reason and the fact that with
efficient exhaust ventilation there should be practically no dangerous
dust, the regulations for the heading of yarn enjoin provision of them
only on written certificate of the Chief Inspector of Factories.
Protection for the clothing, however, where splashing is incidental
to the operations, cannot be dispensed with. Hence either the
overalls themselves or the front of them should be made of some
light ventilated waterproof material, or a waterproof apron worn over
overalls of the kind at present in use. Daily sponging would then take
the place of washing.
If lead dust be visible on the hair of workers, there must be a
defect in the conditions of work to be rectified by other means than
cumbering the head. In our opinion, head coverings ought never to
be necessary. We cannot think that an attack of plumbism can ever
be precipitated by the amount of lead dust inhaled on brushing the
hair.
A common provision in regulations for overalls is:
“Overalls shall be provided for all persons employed in lead processes, and shall
be washed or renewed every week.
“The occupier shall provide and maintain for the use of all persons employed in
lead processes—(a) A cloakroom or other suitable place in which such persons
can deposit clothing put off during working hours, and separate and suitable
arrangements for the storage of overalls required by regulation; (b) a dining-room,
unless all workers leave the factory during meal-hours.
“All persons employed in lead processes shall wear the overalls provided ... and
shall deposit such overalls and any clothing put off during working hours in the
places provided under the regulations. The overalls shall not be removed by
persons employed from the factory or workshop.”

General sense of propriety—and it is on this ground, and not from


danger attaching to non-observance, that we press it—suggests that
overalls should be kept apart from working clothes, and preferably
outside any room in which a lead process is carried on. So long as
actual contact between the two sets of garments is prohibited, we do
not see objection to the same cloakroom sufficing for both. The best
arrangement that we have seen is a room in which each worker has
two lockers—one for the storage of overalls, and the other for
clothing put off during working hours. This presupposes supervision
and effective discipline. We think that all reasonable need in the
provision to be made is met by numbered pegs on one side of the
room or wide passage for clothing, and on the other pegs
correspondingly numbered for the overalls. Means for heating and
drying the clothes should not be overlooked (see Fig. 8).

Fig. 8 shows a good arrangement in a white-lead factory, by which, as is best,


cloakroom, meal-room, and washing and bath accommodation, are all under
one roof. The men on entering hang up their clothes in the private clothes lobby,
and pass through the swinging doors to the lobby where the overalls are hung.
On leaving the factory and at midday they enter by the door leading into the
lobby for storing overalls, and from that pass to the lavatory and bathroom.
Having washed and put on their ordinary clothes, they enter the meal-room. The
building throughout is lined with white glazed bricks.
Fig. 8a.—Well Lighted Mess-Room in a Smelting Works.

Meal-Room Accommodation.—Wherever lead processes are


carried on the provision of a mess-room is called for in a part of the
factory remote from possible contamination from lead dust. This we
hold on general grounds of cleanliness and self-respect, and not
because we think the eating of meals in rooms where lead is used
would noticeably increase the number of cases. The more
conveniently situated in relation to the workrooms the mess-room is,
the more will it be used. Set out briefly, the requirements of a mess-
room are that it should be—
1. Well ventilated, warmed, and lighted.
2. Not less than 10 feet high, and with floor-space ample for each
person likely to occupy it at any one time.
3. Have walls the surface of which is smooth and impervious to a
height of at least 4 feet from the ground.
4. Have pigeon-holes or other arrangement in which each person
can deposit his food separate from that of others.
5. Have means of warming and cooking food.
6. Be kept properly clean and dry.
No part of a factory becomes so unsightly in the absence of daily
cleaning as a mess-room, especially where provision has only to be
made for five or six workers.
Reid[1] has suggested the following scale of floor-space per person
in mess-rooms:
6 persons and under 10¹⁄₂ square feet per person.
Over 6 and up to 12 7¹⁄₂ „ „ „
„ 12 „ 20 6 „ „ „
„ 20 „ 28 5¹⁄₂ „ „ „
„ 28 and any number 5 „ „ „

In a factory well known to us for manufacture of white lead there is


a restaurant originally started in connection with the sick club of the
factory. For fivepence the workman obtains a hot meal of meat,
bread, and vegetables. Any profits go to the sick fund. Since this has
been started improvement in the physical condition of the men has
been marked; several cases of anæmia and malnutrition have
entirely cleared up. No workman, as has already been emphasized,
should commence work in a lead factory unless he has had a good
meal—that is, unless there is some food at least in the stomach—
particularly albuminous food, such as milk, cocoa made with milk, or
café au lait. The most suitable foods generally for lead-workers are
those containing proteids—meat, eggs, milk, cheese, and fatty
foods. Acids—vinegar, pickles, and the like—are especially to be
avoided.
Section 75 (2) of the Factory and Workshop Act, 1901, requires
that, where lead or other poisonous substance is used so as to give
rise to dust or fumes, meal-room accommodation shall be provided.
The question, as a rule, is easily decided, but there are border-line
cases where doubt may arise, as, for example, in letterpress printing
factories in regard to dust, and in soldering operations in regard to
fume. Operations in the composing-room undoubtedly give rise to
dust, and in stereotyping and casting the débris trodden underfoot
causes dust to rise. In linotype rooms, however, in the present state
of knowledge, a difficult burden of proof would rest on the person
who sought to show that dust or fumes were present to such an
extent as to justify action under the section. And the same view
holds, in our opinion, in regard to soldering.
Lavatories.—The usual requirement for this in nearly all
regulations is:
The occupier should provide and maintain in good repair for all persons
employed in lead processes—
(1) Suitable lavatory accommodation, including at least one lavatory basin for
every five such persons, fitted with a waste pipe, or placed in a trough having a
waste pipe, and having a constant supply of hot and cold water laid on; or
alternatively troughs of enamel or similar smooth impervious material, fitted with
waste pipes without plugs, and having a constant supply of warm water laid on,
and affording a length of at least two feet of trough for every five such persons.
(2) Soap, nail-brushes, and a sufficient supply of clean towels, renewed daily.

Discipline, and responsibility placed on some one person to see to


the cleanliness of the lavatory appliances and adequate supply of
the necessary means for washing, can alone insure proper use of
them by the persons employed. The workman has so narrow a
margin of time in which to get his breakfast and dinner that he
cannot be expected to wash if facilities for doing so fail. The
alternative of an enamelled iron trough with jets of warmed water is
in our experience much the most satisfactory installation where the
number employed is more than five or six. Provision of soft soap or
of soap in the form of powder, and nail-brushes nailed to the table,
hinder peculation. Wooden stands for holding wash-basins present
almost invariably a most uninviting appearance unless covered with
sheet lead.
Well-equipped wash-hand basins with hot and cold water laid on
close to the work-place are sometimes provided in addition to the
lavatory proper. If looked after they are valued and used, but if not
they become converted into receptacles for oddments.
Fig. 9.—Good Washing and Bath Accommodation in a Lead Smelting Works.
Fig. 10.—Washing Trough, Douche Baths, and Clothes Cupboards.
Type common on the Continent.

Roller towels should be at least 15 square feet in area for every


three persons employed, and renewed daily.
The merits of soluble sulphides in “akremnin” soap have been
advanced on the ground that the lead is converted into the insoluble
black sulphide, which is thereby made visible to the eye, and the
sight of which will, it is hoped, still further stimulate the desire to
wash. Probably such lead as remains on the hands after well
washing with soap is so closely adherent to the skin as to render risk
of contamination of the food in this way negligible. Dr. Robertson,
Chemist of the Royal Gunpowder Factory at Waltham Abbey, has
found that results as good as those to be obtained from use of
akremnin soap (and without any discoloration of the skin) are
obtained from use of a solution made up as follows: Sal ammoniac
added to saturation to a solution containing 8·5 c.c. of commercial
hydrochloric acid (specific gravity, 1·15) per 100 c.c. of water. The
procedure adopted at Waltham Abbey is—(1) Usual washing with
soap, water, and a nail-brush; (2) scrubbing with the special solution
by means of a nail-brush dipped in it; (3) rinsing in water; and (4)
washing with soap and water.
Sommerfeld[2], from his wide experience, considers that pumice-
soap, with the addition of turpentine, is the best cleansing material
lead-workers can use.
Baths.—Provision of bath accommodation is required under the
special rules for white-lead factories and the regulations for electric
accumulators. In several factories, however, baths are provided for
the use of the workers. They naturally make for improvement in
general health, but we cannot regard provision of them, any more
than cloakrooms and mess-rooms, as likely to influence materially
incidence of lead poisoning in a factory. The three requisites of (1)
convenience and quickness, (2) comfort, and (3) regular use, can
best be secured by the use of shower baths in place of slipper baths.
The advantage they have are—(1) Initial cost of installation is less;
(2) economy in space; (3) economy in water; (4) economy in time
required for bathing; (5) no worker comes into contact with water
used by another; (6) cleansing must be from the head downwards.
Danger of scalding can be absolutely excluded by use of valve
levers, so placed in relation to one another that steam cannot be
turned on until the cold-water valve has been opened, and the heater
can be so arranged that the water is not raised above a definite
temperature.
Separation of Processes.—Lead processes should, as far as
possible, be carried on in such a way that there is aerial
disconnection of one process from another. Separate workrooms,
although desirable unless very small, may not always be possible,
but by exhaust ventilation processes may be arranged so that dust is
not a source of danger to persons working elsewhere. Instances
could be given where, in paint and colour works, persons employed
in the grinding of earth colours, in which no lead entered, succumbed
to attacks of plumbism from contiguity of the plant with that for
grinding lead colours. Threading up of castor runners on a wire
previous to dipping used to be done, prior to 1901, in the dipping-
house itself, with the result that some severe cases of poisoning
occurred. By the rules of 1901 the process was required to be done
in a place separate from any place where dipping (or other
scheduled process) was carried on, and very few cases have
occurred since. And if exhaust ventilation is relied on, Duckering’s
experiments (p. 206) show the attention to detail necessary to
prevent air charged with lead dust being drawn to the spot by the
fan. The need for separation of processes becomes less in
proportion as the cubic space of the room increases, and dust and
fumes are locally removed.
Age of Employment.—The same considerations as have been
stated above govern this point also. Wherever lead dust or fumes
arise, whether exhaust ventilation is applied or not, persons of either
sex under eighteen years of age are probably rather more
susceptible to attack by reason of natural failure to appreciate the
risk run. When periodical medical examination in addition to exhaust
ventilation has been adopted, the age limit can safely be reduced to
sixteen. Where handling only of metallic lead and ordinary soldering
with an iron are done, risk of contracting plumbism is so remote that
an age limit may be unnecessary.
Wall Surface.—Wherever walls are likely to be splashed, as in
dipping rooms and enamelling workshops, the inner surface of the
walls should be of glazed bricks or tiles or enamelled plates, any of
which help also in increasing the light necessary in such rooms. If,
on account of the cost, such perfectly smooth material is
impracticable, the walls should be painted with oil colour, which will
enable them periodically to be wet-cleansed. Dusting the walls is to
be deprecated. Hence accumulations of dust and débris on ledges,
rafters, beams, roofs, etc., should, in our opinion, only very
occasionally be cleaned down. We consider that the risk from one
big cleaning down is less than that from repeated small ones. (See
p. 218).
Floors.—These should be smooth and impervious. Wood
flooring can hardly be regarded as coming within this category; it is
unsuitable where lead processes are carried on. Preference must be
given to floors of concrete and the like material, which can be
washed down easily rather than swept. Frequently the dust raised in
sweeping the floor has determined an attack of lead poisoning. No
objection can be raised to wooden grids and iron roll matting placed
on the concrete floor for the workers to stand on. Cold feet and
transference of lead dust by the boots are lessened by their use.
Where traffic is heavy, as is often the case in lead works, vibration is
set up with wooden floors, and dust disseminated. In smelting works
cast-iron plates are serviceable as flooring.
Instruction of the Worker.—Too much stress cannot be laid on
this point. To insist upon it, however, is useless unless the occupier
has installed the necessary exhaust ventilation, and equipped his
factory with the other essentials for enabling the workman to guard
against dust and free his hands of adhering lead, in whatever form.
When this has been done, then the worker himself can do
something.
Often he creates dust unnecessarily. In shovelling out of a cask
with spade or trowel, in order to get out the last trace of the material
to be transferred, he generally gives it a knock, which causes dust to
fly so sharply as to escape the exhaust; or he removes the
implement quickly from the exhaust, before it has been completely
emptied and while dust is still being given off. He will use a brush to
clean his bench in preference to cleaning it by a wet method. The
printer may hold type between his teeth. Many workers bite their
nails. Moustache and beard may be fingered, and because of this
workers may even be advised to be clean-shaven. They may chew
or smoke constantly while at work, and will frequently eat with
unwashed hands.
Notices enjoining care and cleanliness may be, and often are,
hung up in the workrooms, or a leaflet, such as the one here printed,
is handed to the worker on his first examination by the surgeon.
Nothing, however, can take the place of actual verbal instruction
from occupier, foreman, and fellow-worker impressed with the
importance of the matter.

Lead Poisoning: how Caused and how best Prevented.


Unless great care is taken, work in lead and lead compounds is injurious to
health, because the lead enters the system and causes lead poisoning.
Danger is greatest from breathing leady dust or fume, but eating with unwashed
hands, and biting nails or putting such things as sweets or pipes into the mouth
while the fingers are soiled with lead, all help to cause poisoning.
Many workers in lead have a blue line round the edge of the gums, but the first
actual symptoms of the injurious action of lead on the system are costiveness,
colicky pains in the stomach, headache, and marked paleness. Occasionally
headache is associated with epileptic fits, a very serious condition, which may be
followed by loss of sight. “Wrist-drop,” loss of power in the muscles moving the
fingers and wrist, results sometimes from lead poisoning, and may cause
permanent disablement from work. It does not usually come on until after a person
has worked in lead for some years.
Lead, even if absorbed in small quantities, has a tendency to remain in the
system, and if care be not taken it will go on accumulating, so that in time the
health may become permanently damaged, even without any definite attack
recognized as lead poisoning.
Girls and boys, because they are not so likely to observe the necessary
precautions as grown-up people, should be closely watched. Women should be
especially careful, as the injurious effect of lead in them may seriously interfere
with the healthiness of their children.
As lead does not enter the system through the pores of the skin, it can in great
measure be avoided by—
1. Taking special care to avoid raising dust. It is to the interest of everyone to
see that ventilating arrangements are in order for carrying dust away at
the point where it is produced.
Any little cloud constantly made at work is sure, if breathed, to set up lead
poisoning. Where lead colours are used wet, danger arises from the
splashing of the material and its subsequent drying into dust.
2. Paying scrupulous attention to cleanliness of the hands, face, teeth, and
clothing. The hands and nails should always be cleaned with soap and
nail-brush before food is eaten, and it is a wise practice also to wash out
the mouth. The teeth should be brushed at least once a day, preferably
before the evening meal.
3. Never commencing work on an empty stomach. Food containing fat, such
as bacon and milk, is suitable.
Overall suits, if worn, should never be shaken to rid them of dust. They require
washing at least once a week.
Aperient medicine, such as Epsom salts (one or two teaspoonfuls in water), can
be taken once or twice a week with advantage by lead-workers.
Experience shows that the habits and home life of the workers influence their
liability to lead poisoning. Intemperate persons are the first to fall victims. Those
who begin work on an empty stomach incur additional risk by so doing.
Carefulness while at work, and cleanliness, offer the best means of escaping
attacks of lead poisoning.
Those who work in lead should keep in mind every hour of every working day
the importance of not breathing lead dust and not carrying lead to the mouth in any
way.
Medical advice should at once be obtained if signs of lead poisoning present
themselves.

REFERENCES.
[1] George Reid: Memorandum on Mess-room Accommodation: Appendix
XXV. of the Potteries Committee’s Report, vol. ii., 1910. Cd. 5278.
[2] Th. Sommerfeld: Die Bekämpfung der Bleigefahr, edited by Leymann,
p. 76.
CHAPTER XV
DESCRIPTION OF PROCESSES
Lead smelting—Red and orange lead and litharge—Letterpress printing—File-cutting—File-hardening—
Tinning of metals—Plumbing and soldering—Brass.

Lead Smelting and Silver Refining.—Lead poisoning very rarely occurs in lead
mining in Europe, as galena (sulphide of lead), the principal ore in which the metal is
found, is insoluble. Galena always, and other lead ores very often, contain a small
proportion of silver, ranging from 0·001 to 1 per cent., and at times traces of gold.
Owing to the great affinity of lead for silver, lead smelting is necessarily a process
preliminary to the extraction of silver and gold from it[1].
Lead ores, drosses, etc., on arrival at the factory, are, after sampling, deposited in
bins or heaps (often in the open air), and watered to prevent dust. All ores may, and
refractory ores (containing over 4 per cent. silica) and dross must, be smelted in a blast
furnace by aid of coke. The bulk of the charge in a blast furnace may consist of more
or less complex ores of the precious metals, especially silver.
When galena is treated in a blast furnace, preliminary roasting is indispensable, and
in many smelting works its treatment takes place in a reverberatory or open-hearth
furnace, and not in a blast furnace.
The three principal methods applicable to extraction of lead from ores are—(1) The
roast and reaction method; (2) the roast and reduction method; and (3) the
precipitation process.
By the roast and reaction method a part of the galena is first converted into oxide
and sulphate of lead with access of air. Subsequently, on shutting off the air-supply and
increasing the temperature, a reaction takes place. The sulphur in the unchanged
sulphide combines with the oxygen of the oxide and sulphate to form sulphur dioxide,
which is carried away by the draught into the bricked flue, leaving metallic lead behind.
The process is carried on in a reverberatory or open-hearth furnace.
In the roast and reduction method the first portion of the process is carried out in a
reverberatory furnace, the galena being roasted pretty completely to lead oxide and
sulphate, which are then—usually in a blast furnace—reduced to the metallic state with
coke and other reducing agents, such as iron.
By the precipitation process galena was decomposed at a high temperature by
means of metallic iron, forming a mixture of iron and lead sulphide. This method was
only applicable to rich lead ores, and is now given up.
The three methods are hardly ever independent of one another, as the rich slag or
residues, for instance, which are obtained by the first method are retreated by the
second, and the second is, as has been stated, almost always combined with the first.
On tapping the blast or reverberatory furnace, the lead is drawn off into a lead well or
sump, from which, when cool, it is ladled into moulds, while the slag is run into
movable metal pots or along specially-prepared channels. The slag run off from the
reverberatory furnace contains much lead locked up as silicate, which requires to be
retreated, usually in the blast furnace. During the roasting process much raking of the
material is necessary. The slag from the blast furnace should contain less than 1 per
cent. of lead.
On the Continent and in America, the Huntingdon-Heberlein process has been
extensively adopted, with lessened incidence of poisoning, the result of mechanical
methods of working, obviating hand labour, and the low temperature (diminishing risk
from lead fume) at which the roasting is carried on. In this process the crushed ore is
desulphurized by first mixing with lime and heating in presence of air in a revolving
furnace, provided with automatic rabble, at moderate temperature (about 700° C.).
Subsequently the roasted material is conveyed from closed bins, into which it falls
automatically, by dust-proof elevators to a converter, in which atmospheric air at slight
pressure is forced through it. The agglomerated mass so formed, when tipped out of
the converter (in doing which there is risk from dust), is well damped, broken by hand,
and charged with coke in the usual way into the blast furnace.
In some lead-smelting works the material arrives on the premises in the form of
ingots of base bullion—i.e., impure lead rich in silver—the product of previous smelting
of the ore where it is mined in Australia or Spain. And one of the main objects of the
blast-furnace smelting of galena in the factory is to produce a base bullion rich in
precious metals. The lead so obtained requires further softening or refining to get rid of
copper, antimony, arsenic, and tin. This is effected in a reverberatory furnace, first at a
low temperature to allow of formation of furnace dross, which is removed through the
working doors, and secondly with increase of heat and access of air to oxidize, in the
order named, the tin, arsenic, and antimony. Finally the lead is tapped into kettles or
pots. If free from silver, such lead, when poured into moulds, is ready for the market;
but if rich in silver, it is treated for the recovery of that metal either by (a) Pattinson’s
process, depending on the higher temperature of crystallization of lead than of an alloy
of lead and silver, which enables a separation of one from the other to be made by a
process of ladling the crystalline from the liquid portion; or, much more commonly, by
(b) Parkes’s process, depending on the formation, on addition of zinc to a pot of molten
lead, of crusts consisting of an alloy of silver, lead, and zinc. The crusts obtained in the
latter process, after cooling, are broken up, placed in a crucible, and the zinc driven off
at a temperature of 1,000° C. in a dezincing Faber du Faur retort. The rich bullion,
retained either in the last kettle by the Pattinson process, or remaining in the crucible
after dezincing, next undergoes cupellation—i.e., exposure to a blast of air in a
furnace. The lead is oxidized into litharge, which drops into a receptacle below the
furnace, leaving the silver behind. In all lead-smelting works the draught from the
furnace carries much dust of ore and fuel, and fume, consisting of sulphide, sulphate,
and oxides of lead, into the flues. The dust is easily collected in dust chambers, but the
fume requires ducts of great length—sometimes a mile or more—in which to deposit.
Dangers and Prevention.—The risk from dust in general labouring work, in
depositing the ores in bins, in removing them to, and charging them into, the furnace,
can only be controlled by watering, preferably by a spray. From the blast furnace lead
fume and carbon monoxide may escape at the point where charging is done, if there is
back pressure from blockage in the flues, or if the furnace blast is not working perfectly.
In tapping the lead and in manipulations such as charging, drossing, and skimming,
conducted through the doors of furnaces of all descriptions, hoods, extending at the
sides down to the floor level, require to be arranged over the working doors, and
connected either with ducts passing vertically through the roof or directly with the
exhaust created in the furnace or flue itself. Dross and skimmings removed through the
working doors should be received into iron trolleys capable of being covered, and not
be allowed to fall on to the floors, to be shovelled up later on to barrows. Before such
dross or slag from reverberatory furnaces is broken up for further treatment it should
be well watered.
Lead absorption among the men actually employed in the Pattinson and Parkes’s
processes is comparatively rare, as the temperature of the molten metal does not
exceed 450° to 500° C. When, however, the zinc-silver-lead and gold alloy is removed
for treatment in special furnaces for distillation off of the zinc, prior to cupellation, the
lead from the Parkes’s pot, now free from silver, but containing traces of zinc,
antimony, and other impurities, is run in some works into what are termed “market
pots” for a final refining. Air and steam are blown through to oxidize the impurities. The
pot is skimmed twice, the first dross containing antimony, etc., and the second a fine
dust consisting of lead (60 per cent.) and zinc. The risk of poisoning at this point is
considerable, although an exhaust fan connects up the cover of the pot with a cyclone
separator, to carry away the fume when the steam is blown through. In other works this
dezincing is done in a refining furnace, the material being then in a slaggy state, thus
hindering development of fumes. After the condensation of the zinc in the distillation of
the silver-lead and zinc crust the cover of the pot is raised, and the remaining metal,
containing 80 per cent. of lead at a temperature of about 2,000° F., is ladled out into
moulds for treatment in the cupelling furnace. The temperature at which this ladling
operation has to be done makes the work impossible for those unaccustomed to it.
Exhaust ventilation in the operation of emptying the pot, and cutting off the heat by a
water-cooled jacket, suggest themselves as means to combat the undoubted risk.
In cupellation the temperature is high (about 2,000° C.), and fume will escape from
the working door and from the opening where the rich lead is fed into the furnace. The
danger here is sufficiently recognized by hoods and ducts placed in front of the
furnace, but the draught, unless the ducts are connected up with a high-pressure fan,
may prove inadequate to carry away all the fume.
Flue-cleaning, carried out usually at quarterly or half-yearly periods, is dusty work, as
much of the dust is in so fine a state of division as to repel contact with water.
Smelting of other metals when the ores contain appreciable amounts of lead is
equally productive of plumbism. Thus, in the year 1901 fourteen cases were reported
from an iron works for the manufacture of spiegeleisen, the ore (now no longer used)
coming from Greece[2]. In previous years it would appear to have been even greater. A
remarkable feature of all the reported cases from this factory was that the form
assumed was colic, and never paralysis. The poisoning was due to vaporization of the
molten lead by the very high temperature to which it was raised as the molten iron
flowed out of the furnace on tapping. The danger from fume was limited to the first few
feet of the channel, as the heavier molten lead gravitated down between loose
brickwork into a pit. Dust collected above the point where the furnace was tapped
contained 39·77 per cent. of lead monoxide, and the flue dust 4·22 per cent.[3]. A
flannel respirator worn once only by one of the furnace men contained lead equal to 16
milligrammes of lead monoxide. In 1906 three cases were reported in the extraction of
copper. The persons affected were employed in charging ore into the cupola[4].
Heavy incidence of poisoning (twelve cases in two months) in a smelting works (now
closed) led to examination of sixteen men. The gums of only one man were free of a
blue line—in most it was particularly dense—eight were anæmic, one had paralysis of
the wrists, and five others weakness. Analysis of the air was made at different points in
the factory by the chemist of the works, G. D. Cowan, with the following results:
The samples from the cupola were taken from inside the hood (about 5 feet above the men’s heads).
The gas was filtered through cotton-wool, so that all solid particles were retained, and the remaining gas
was treated separately. The solid particles will be called “dust,” and the gas, after filtration, “fume.”
The cupola samples on being examined gave—
Dust, first sample 0·08152 grain of lead per cubic foot.
„ second sample 0·07297 „ „ „
Fume, first sample
- 0·00526 „ „ „
„ second sample
The samples from the lead well were taken 12 inches above the molten metal at the end of the lead
siphon, and gave the following results:
Dust 0·05653 grain per cubic foot.
Fume Nil.
The briquetting machine samples were taken from the platform where all the ore and fluxes are mixed
before briquetting.
The results obtained here were as follows:
Dust 0·95715 grain of lead per cubic foot.
Fume, or fine dust that passed through filter 0·01314 „ „ „
The reason for these high results was owing to dust raised when waggons of ore were tipped prior to
mixing.

Assuming that 20 cubic inches of air pass in and out of the lungs at each respiration,
a man in eight hours would inhale and exhale 94·4 cubic feet. This amount of air,
inhaled at the position in the cupola where the sample was taken, would contain
7·3818 grains of lead; at the lead well, 5·3064 grains; and at the briquetting machines,
91·5953 grains. Although the condition of the air where the men actually worked must
have contained much less than these amounts, the analyses quite serve to explain the
heavy incidence.
Collis[5] quotes the following analysis of dust and fumes from Hofman’s “Metallurgy
of Lead.”
Lead Smelting: Analyses of Dust and Fumes (from Hofman’s “Metallurgy of
Lead”).

Percentage of—
Material Arsenious Lead Lead
Analysed. Arsenic. Oxide. Lead. Monoxide. Sulphate.
(1) (2) (3) (4) (5) (6)
All dust collected in ten years, average — — 25·6 — —
Dust from—
Downcomers of eleven blast furnaces — — 47·5 — —
Roof of blast-furnace building — — 27·1 — —
Fumes from—
Slag pot while boiling — 4·8 — 41·0 26·2
Reverberatory settling furnace 2·3 — — 31·0 —
Flue dust—
Friedrichshütte, Silesia — — — 62·8 —
A 7·5 — 26·2 — —
Freiberg, Saxony - B 37·5 — 21·3 — —
C 46·4 — 16·2 — —
Pribram, Bohemia — 1·0 — 45·5 —

Collis[6] estimated the attack rate in lead-smelting works at 30, and in spelter works
at 10, per 1,000 per annum. In one factory he found it 80 per 1,000, and in a spelter
works five cases occurred in a few months among seven workers.
The distribution of the reported cases from year to year was as follows:

Process. 1900. 1901. 1902. 1903. 1904. 1905. 1906. 1907. 1908. 1909. 1910. 1911. Total.
Lead
smelting 21 26 13 13 7 10 16 21 31 28 21 33 240
Desilverizing 1 3 9 10 16 6 9 4 3 6 — 3 70
Spelter 5 11 3 4 4 5 9 2 31 25 12 11 122
Other
(copper,
iron, etc.) 7 14 3 10 6 3 4 1 5 7 1 1 62
34 54 28 37 33 24 38 28 70 66 34 48 494
Spelter (Zinc) Manufacture.—Lead is present in zinc ores in a proportion of from
1 to 10 per cent. (usually 3 per cent.). Despite this small proportion, incidence of
chronic plumbism among those engaged in the manufacture is high, as in the present
state of knowledge the lead fume given off in distillation of the zinc cannot be efficiently
removed. Blende (zinc sulphide) is first calcined, and the residue, after mixture with
calamine (zinc ashes) and anthracite, forms the charge for the furnace. The retorts are
arranged in long rows one above the other, and frequently back to back in the furnace,
so that there may be 250 or more to each furnace, and of the furnaces there may be
several in a shed. Attached to the retort is a fireclay receptacle (condenser) into which
the zinc distils, and an iron nozzle (prolong) to prevent oxidation in the condenser.
While distillation goes on the carbonic oxide gas evolved burns brightly, tinged with the
greenish-white colour imparted by the zinc. The products of combustion, with traces of
lead fume from the hundreds of prolongs, are discharged into the atmosphere of the
sheds, where temperature is high. The latest design of prolongs, however, has an exit
at which the products of combustion escape near the furnace, so that the greater
portion pass up into the ventilating hoods. Periodically—three times to each charge—
the workman removes the prolong, ladles out such zinc as has condensed, and pours
it into moulds. Finally, when distillation is completed, the contents of the retorts are
raked out, and it is in the fuming hot residues so deposited on the floors that much of
the danger arises. In distilling furnaces of modern design the hot residues fall through
openings in the window of the furnaces into “pockets,” in which they cool off
considerably before they are drawn out into iron skips. In another form of furnace used
in the manufacture of spelter (Silesian), the workman after charging can leave the
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