Back to Main page for the programming language Joy
Revised February 2003
This revision includes references to John Cowan's (2001) extension.
Abstract: Joy is a functional programming language which is not based on the application of functions to arguments but on the composition of functions. It does not use lambda-abstraction of expressions but instead it uses quotation of expressions. A large number of what are called combinators are used to perform dequotation, they have the effect of higher order functions. Several of them can be used to eliminate recursive definitions. Programs in Joy are compact and often look just like postfix notation. Writing programs and reasoning about them is made easy because there is no substitution of actual for formal parameters.
This tutorial describes basic features of the language Joy which are likely to be the same in all implementations.
Keywords: functional programming, higher order functions, composition of functions, combinators, elimination of recursive definitions, variable free notation
The remainder of this paper is organised as follows: This introductory section continues with a very short outline of some distinguishing features of the language. The next two sections introduce the basic data types and operations on them. The section after that returns to the central feature of Joy: quotations of programs and their use with combinators. After a short section on definitions the next section resumes the discussion of combinators, in particular those that can eliminate the need for recursive definitions. In the final section several short programs and one larger program are used to illustrate programming with aggregates in Joy.
To add two integers, say 2 and 3, and to write their sum, you type the
program
2 3 +This is ordinary postfix notation, a reverse form of a notation first used by Polish logicians in the 1920s. Its advantage is that in complex expressions no parentheses are needed. Internally it works like this: the first numeral causes the integer 2 to be pushed onto a stack. The second numeral causes the integer 3 to be pushed on top of that. Then the addition operator pops the two integers off the stack and pushes their sum, 5. The system reads inputs like the above and executes them when they are terminated by a period
"."
, like this:
2 3 + .In the default mode there is no need for an explicit output instruction, so the numeral
5
is now written to
the output file which normally is the screen.
So, in the default mode the terminating "."
may be
taken to be an instruction to write the top element of the stack.
In what follows the terminating period will not be shown any further.
Apart from integers, the current version of Joy as extended by John Cowan
has real numbers or "floats".
Arithmetic operations on floats are just like those on integers.
The following multiplies two numbers
2.34 5.67 *and leaves their product,
13.2678
, on top of the stack.
(So, to see the result on the terminal, the above line has to terminated by
a period.)
To compute the square of an integer, it has to be multiplied by
itself. To compute the square of the sum of two integers, the sum has
to be multiplied by itself. Preferably this should be done without
computing the sum twice.
The following is a program to compute the square of the sum of 2 and 3:
2 3 + dup *After the sum of 2 and 3 has been computed, the stack just contains the integer 5. The dup operator then pushes another copy of the 5 onto the stack. Then the multiplication operator replaces the two integers by their product, which is the square of 5. The square is then written out as 25. Apart from the
dup
operator there are several others for re-arranging the top of the
stack. The pop operator removes the top element, and the
swap operator interchanges the top two elements.
This is quite different from proper postfix notation,
because the stack manipulators only make sense in the presence
of a stack. Such notation is also used in some pocket calculators,
the Unix utility dc, the typesetting language Postscript
and the general purpose language Forth.
Billy Tanksley has suggested that this be called
concatenative notation.
The theory of this notation is a topic unto itself,
but it will not be dealt with in this tutorial.
A list of integers is written inside square brackets. Just
as integers can be added and otherwise manipulated, so lists can be
manipulated in various ways. The following concatenates
two lists:
[1 2 3] [4 5 6 7] concatThe two lists are first pushed onto the stack. Then the
concat
operator pops them off the stack and pushes the
list [1 2 3 4 5 6 7]
onto the stack. There it may be
further manipulated or it may be written to the output file.
The elements of a list need not be all of the same type,
and the elements can be lists themselves.
The following uses a list containing one integer, two floats
and one list of three integers.
[ 3.14 42 [1 2 3] 0.003 ] dup concatThe dup operator will push a copy of the list on top of the stack, where the two lists will then be concatenated into one.
Joy makes extensive use of combinators. These are like
operators in that they expect something specific on top of the stack.
But unlike operators they execute what they find on top of the stack,
and this has to be the quotation of a program, enclosed in
square brackets. One of these is a combinator for mapping
elements of one list via a function to another list. Consider the
program
[1 2 3 4] [dup *] mapIt first pushes the list of integers and then the quoted program onto the stack. The
map
combinator then removes the list and
the quotation and constructs another list by applying the program to
each member of the given list. The result is the list [1 4 9
16]
which is left on top of the stack.
In definitions of new functions no formal parameters are
used, and hence there is no substitution of actual parameters for
formal parameters. After the following definition
square == dup *the symbol
square
can be used in place of dup *
.
Definitions occur in blocks such as the following:
DEFINE square == dup * ; cube == dup dup * * .As the example shows, definition mode is initiated by the reserved word
DEFINE
and extends to the period.
Individual definitions are separated by semicolons.
In libraries the initiator LIBRA
is used
instead of DEFINE
.
In the remainder of this paper the initiator, the separator
and the terminator will generally not be shown any further.
As in other programming languages, definitions may be recursive, for
example in the definition of the factorial function. That definition
uses a certain recursive pattern that is useful elsewhere. In Joy
there is a combinator for primitive recursion which has this
pattern built in and thus avoids the need for a definition. The
primrec combinator expects two quoted programs in addition
to a data parameter. For an integer data parameter it works like
this: If the data parameter is zero, then the first quotation has to
produce the value to be returned. If the data parameter is positive
then the second has to combine the data parameter with the result of
applying the function to its predecessor. For the factorial function
the required quoted programs are very simple:
[1] [*] primreccomputes the factorial recursively. There is no need for any definition. For example, the following program computes the factorial of
5
:5 [1] [*] primrecIt first pushes the number
5
and then it pushes the two
short quoted programs. At this point the stack contains three
elements. Then the primrec
combinator is executed. It
pops the two quotations off the stack and saves them elsewhere. Then
primrec
tests whether the top element on the stack
(initially the 5
) is equal to zero. If it is, it pops it
off and executes one of the quotations, the [1]
which
leaves 1
on the stack as the result. Otherwise it pushes
a decremented copy of the top element and recurses. On the way back
from the recursion it uses the other quotation, [*]
, to
multiply what is now a factorial on top of the stack by the second
element on the stack. When all is done, the stack contains
120
, the factorial of 5
.
As may be seen from this program, the usual branching of recursive
definitions is built into the combinator. The primrec
combinator can be used with many other quotation parameters to compute
quite different functions. It can also be used with data types other
than integers.
Joy has many more combinators which can be used to calculate many
functions without forcing the user to give recursive or non-recursive
definitions. Some of the combinators are more data-specific than
primrec
, and others are far more general.
An integer is just a whole number. Literals of this type are
written in decimal notation. The following binary operations are
provided:
+ - * / remThe first four have their conventional meaning, the last is the operator for the remainder after division. Operators are written after their operands. Binary operators remove two values from the top of the stack and replace them by the result. For example, the program
20 3 4 + * 6 - 100 remevaluates to 34, and this value is left on top of the stack. There are also some unary operators specific to integers like the abs operator which takes the absolute value, and the signum operator which yields
-1
,
0
or +1
, depending on whether its parameter
is negative, zero or positive.
Apart from the positive and negative integers or whole numbers,
Joy has floating point numbers or "floats".
Literals of this type are written with a decimal point and at least
one digit after that. Optionally the last digit may be followed by
'E' or 'e' and then a positive or negative exponent.
Here are some examples:
3.14 314.0 3.14E5 3.14e-5The last two are equivalent to 314000.0 and 0.0000314 . Most operators on integers work in the same way for floats. John Cowan's extension also provides a large number of functions for floats, but these are outside the scope of this tutorial.
A character is a letter, a digit, a punctuation character, in
fact any printable character or one of a few white space characters.
Literals of type character are written as a single quote followed by
the character itself. Values of type character are treated very much
like small numbers. That means that other numbers can be added to
them, for example 32 to change letter from upper case to lower case.
There are two unary operators which are defined on characters and on
integers: pred takes the predecessor, succ takes
the successor. For example,
'A 32 + succ succevaluates to
'c
, the third lower case letter.
The type of truth values is what in some languages is called
Boolean. The following are the two literals, the unary
negation operator and two binary operators for conjunction and
disjunction:
true false not and orFor example, the program
false true false not and not orevaluates to
false
.
Values of type integer and character can be compared using the
following relational operators:
= < > != <= >=The != operator returns the negation of what the = operator returns. The others have the conventional meaning. As all operators, they are written in postfix notation. The result is always a truth value. For example,
'A 'E < 2 3 + 15 3 / = andevaluates to
true
.
A set is an unordered collection of zero or more small
integers. Literals of type set are written inside curly braces, and
the empty set is written as an empty pair of braces. For set literals
the ordering of the elements is irrelevant and duplication has no
effect. The operators for conjunction and disjunction are also
defined on sets. For example, the two equivalent programs
{1 3 5 7} {2 4 6 8} or {} or {3 4 5 6 7 8 9 10} and {3 7 5 1} {2 4 6 8} or {} or {3 4 5 6 7 8 9 10 10} andevaluate to
{3 4 5 6 7 8}
. The negation operator
not takes complements relative to the largest expressible
set, which in most implementations will have a maximum of 32 members:
from 0
to 31
.
A string is an ordered sequence of zero or more characters.
Literals of this type string are written inside double quotes, and the
empty string is written as two adjacent double quotes with nothing
inside: ""
. Note that this is different from the string
containing just the blank: " "
. Two strings can be
concatenated, and a string can be reversed. For example,
"dooG" reverse " morning" " " concat concat "world" concatevaluates to
"Good morning world"
.
For many operators an implementation can choose whether to make it
a primitive or define it in a library.
Apart from execution speed,
to the user it makes no difference as to which choice has been
made.
In the current implementation the reverse
operator
is defined in a library.
A list is an ordered sequence of zero or more values of any type. Literals of type list are written inside square brackets, the empty list is written as an empty pair of brackets. Lists can contain lists as members, so the type of lists is a recursive data type.
Values of the aggregate types, namely sets, strings and lists can be
constructed from existing ones by adding a new member with the
cons operator. This is a binary operator for which the
first parameter must be a possible new member and the second parameter
must be an aggregate. For sets the new member is added if it is not
already there, and for strings and lists the new member is added in
front. Here are some examples. The programs on the left evaluate to
the literals on the right.
5 3 {2 1} cons cons 3 swap cons {1 2 3 5} 'E 'C "AB" cons cons 'C swap cons "CECAB" 5 [6] [1 2] cons cons 'A swap cons ['A 5 [6] 1 2]As the examples show, the
cons
operator is most useful
for adding elements into an aggregate which is already on the stack
below the aggregate. To add new elements that have just been pushed,
the new elements and the aggregate have to be swap
ped
first before the new element can be cons
ed into the
aggregate. To facilitate this, Joy has another operator,
swons, which first performs a swap
and then a
cons
.
Whereas the cons
and swons
operators builds
up aggregate values, the two unary operators first and
rest take them apart. Both are defined only on non-empty
aggregate values. For the two ordered aggregate types, strings and
lists, the meaning is obvious: the first operator returns the first
element and the rest operator returns the string or list without the
first element:
"CECAB" first 'C "CECEB" rest "ECAB" ['A 5 [6] 1 2] first 'A ['A 5 [6] 1 2] rest [5 [6] 1 2]But sets are unordered, so it does not make sense to speak of their first members as sets. But since their members are integers, the ordering on the integers can be used to determine what the first member is. Analogous considerations apply to the
rest
operator.
{5 2 3} first 2 {5 2 3} rest {3 5}
For all three types of aggregates the members other than the first can
be extracted by repeatedly taking the rest and finally the first of
that. This can be cumbersome for extracting member deep inside. An
alternative is to use the at operator to index
into the aggregate, by extracting a member at a numerically
specified position. For example, the following are two equivalent
programs to extract the fifth member of any aggregate:
rest rest rest rest first 5 at
There is a unary operator which determines the size of any
aggregate value. For sets this is the number of members, for strings
its is the length, and for lists it is the length counting only top
level members. The size
operator yields zero for empty
aggregates and a positive integer for others. There is also a unary
null operator, a predicate which yields the truth value
true
for empty aggregates and false
for
others. Another predicate, the small operator, yields
true
just in case the size is 0
or
1
.
Apart from the operators which only affect the stack, there are two
for explicit input and output. The get operator reads an
item from the input file and pushes it onto the stack. The
put operator pops an item off the stack and writes it to
the screen or whatever the output file is. The next program reads two
pairs of integers and then compares the sum of the first pair with the
sum of the second pair.
get get + get get + > putThe two get operators attempt to read two items and push them onto the stack. There they are immediately added, so they have to be integers. This is repeated for the second pair. At this point the stack contains the two sums. Then the comparison operator pops the two integers and replaces them by a truth value, true or false, depending on whether the first sum is less than the second sum. The put operator pops that truth value and writes it. The stack is now as it was before the program was run, only the input file and the output file are changed.
 put "Hello, " get concat putFirst the question string is pushed on the stack and then popped to be written out to the screen. Then the '"Hello, "' string is pushed. Next, the
get
operator reads an item from the
keyboard and pushes it onto the stack. That item has to be another
string, because it will be concatenated with what is below it on the
stack. The resultant string is then written out. So, if in answer to
the question a user types '"Pat"', the program finally writes out
'"Hello, Pat"'.
In addition to the compound data types set, string and list, John Cowan's extension provides a large number of operators for manipulating the file system: opening, closing, deleting files, and various input-output operators. These are outside the scope of this tutorial.
[ + 20 * 10 4 - ]has size
6
, its second and third elements are
20
and *
, it can be reversed or it can be
concatenated with other quotations. But passive quotations can also
be made active by dequotation.
If the above quotation occurs in a program, then it results in the quotation being pushed onto the stack - just as a list would be pushed. There are many other ways in which that quotation could end up on top of the stack, by being concatenated from its parts, by extraction from a larger quotation, or by being read from the input. No matter how it got to be on top of the stack, it can now be treated in two ways: passively as a data structure, or actively as a program. The square brackets prevented it from being treated actively. Without them the program would have been executed: it would expect two integers which it would add, then multiply the result by 20, and finally push 6, the difference between 10 and 4.
Joy has certain devices called combinators which cause the execution of quoted programs that are on top of the stack. This section describes only a very small proportion of them.
One of the simplest is the i combinator. Its effect is to
execute a single program on top of the stack, and nothing else.
Syntactically speaking, its effect is to remove the quoting square
brackets and thus to expose the quoted program for execution.
Consequently the following two programs are equivalent:
[ + 20 * 10 4 - ] i + 20 * 10 4 -The
i
combinator is mainly of theoretical significance,
but it is used occasionally. The many other combinators are essential
for programming in Joy.
One of the most well-known combinators is for branching. The
ifte combinator expects three quoted programs on the stack,
an if-part, a then-part and an else-part, in that order, with the
else-part on top. The ifte
combinator removes and saves
the three quotations and then performs the following on the remainder
of the stack: It executes the if-part which should leave a truth value
on top of the stack. That truth value is saved and the stack is
restored to what it was before the execution of the if-part. Then, if
the saved truth value was true
, the ifte
combinator executes the then-part, otherwise it executes the
else-part.
In most cases the three parts would have been pushed in that order
just before the ifte
combinator is executed. But any or
all of the three parts could have been constructed from other
quotations.
In the following example the three parts are pushed just before the
ifte
combinator is executed. The program looks at a
number on top of the stack, and if it is greater than 1000 it will
halve it, otherwise it will triple it.
[1000 >] [2 /] [3 *] ifte
Some combinators require that the stack contains values of certain
types. Many are analogues of higher order functions familiar from
other programming languages: map, filter and
fold. Others only make sense in Joy. For example, the
step combinator can be used to access all elements of an
aggregate in sequence. For strings and lists this means the order of
their occurrence, for sets it means the underlying order. The
following will step
through the members of the second
list and swons
them into the initially empty first list.
The effect is to reverse the non-empty list, yielding [5 6 3 8
2]
.
[] [2 8 3 6 5] [swons] step
The map combinator expects an aggregate value on top of the stack, and it yields another aggregate of the same size. The elements of the new aggregate are computed by applying the quoted program to each element of the original aggregate. An example was already given in the introduction.
Another combinator that expects an aggregate is the filter
combinator. The quoted program has to yield a truth value. The
result is a new aggregate of the same type containing those elements
of the original for which the quoted program yields true
.
For example, the quoted program ['Z >]
will yield truth
for characters whose numeric values is greater than that of
Z
. Hence it can be used to remove upper case letters and
blanks from a string. So the following evaluates to
"ohnmith"
:
"John Smith" ['Z >] filter
Sometimes it is necessary to add or multiply or otherwise combine all
elements of an aggregate value. The fold combinator can do
just that. It requires three parameters: the aggregate to be folded,
the quoted value to be returned when the aggregate is empty, and the
quoted binary operation to be used to combine the elements. In some
languages the combinator is called reduce (because it turns the
aggregate into a single value), or insert (because it looks as though
the binary operation has been inserted between any two members). The
following two programs compute the sum of the members of a list and
the sum of the squares of the members of a list. They evaluate to 10
and 38, respectively.
[2 5 3] 0 [+] fold [2 5 3] 0 [dup * +] fold
To compute the average or arithmetic mean of the members of a set or a
list, we have to divide the sum by the size. (Because of the integer
arithmetic, the division will produce an inaccurate average.) The
aggregate needs to be looked at twice: once for the sum and once for
the size. So one way to compute the average is to duplicate the
aggregate value first with the dup operator. Then take the
sum
of the top version. Then use the swap
operator to interchange the position of the sum and the original
aggregate, so that the original is now on top of the stack. Take the
size of that. Now the stack contains the sum and the size, with the
size on top. Apply the division operator to obtain the average value.
dup 0 [+] fold swap size /One nice feature of this little program is that it works equally for set values as for list values. This is because the constituents
fold
and size
work for both types.
But there are two aspects of this program which are unsatisfactory.
One concerns the dup
and swap
operators
which make the program hard to read. The other concerns the
sequencing of operations: The program causes the computation of the
sum to occur before the computation of the size. But it does not
matter in which order they are computed, in fact on a machine with
several processors the sum and the size could be computed in parallel.
Joy has a combinator which addresses this problem: there is
one data parameters, the aggregate, which is to be fed to two
functions. From each of the functions a value is to be
constructed, by calling both functions by means of a combinator
cleave which produces two values,
one for the sum and one for the size.
The program for the average looks like this:
[0 [+] fold] [size] cleave /
x
,
y
... For example, the squaring function might be
defined by some variation of any of the following:
square(x) = x * x (defun (square x) (* x x)) square = lambda x.x * xIn Joy formal parameters such as
x
above are not
required, a definition of the squaring function is simply
square == dup *This is one of the principal differences between Joy and those languages that are based on the lambda calculus. The latter include (the purely functional subsets of) Lisp, Scheme, ML and Haskell. All of these are based on the application of functions to arguments or actual parameters.
In definitions and abstractions of functions the formal parameters
have to be named - x
, y
and so on, or
something more informative. This is different in Joy. It is based on
the composition of functions and not on the application of functions
to arguments. In definitions and abstractions of functions the
arguments do not need be named and as formal parameters indeed cannot
be named. One consequence is that there are no environments
of name-value pairs. Instead the work of environments is done by
higher order functions called combinators.
Finally, the concrete syntax of the language is an integral part of the language and aids in reasoning about Joy programs in the metalanguage.
Suppose it is required to transform a list of numbers into the list of
their cubes. The cube of a single number is of course computed by
dup dup * *It would be possible to introduce a definition of the cube function. But that would introduce another name,
cube
. If the cube
function is used only once for computing the cubes of a list of
numbers, then it may not be desirable to give a definition of it at
all. In Joy the list of cubes is computed by the first line below,
but it is also possible to give an explicit definition as in the
second line.
[dup dup * *] map cubelist == [dup dup * *] mapIn a language that is based on the lambda calculus both would need a lambda abstraction with a variable, say
x
, for the number
to be cubed. And of course the second line would need an additional
formal parameter, say l
, or a lambda abstraction with a
variable l
for the list to which the cubelist function is
to be applied.
Suppose now that it is required to transform a list of lists
of numbers into the list of lists of their cubes. One might
give the definition
cubelistlist == [ [dup dup * *] map ] mapOf course, if that function is only to be used once, one might not bother to give a definition at all but use the right hand side directly. In languages based on abstraction, at least two formal parameters are needed just for the right hand side, and another for the definition itself. For example, in Scheme the definition looks like this:
(define (cubelistlist ll) (map (lambda (l) (map (lambda (n) (* n (* n n))) l ) ) ll )Here the two formal parameters are
n
for the number and
l
for the list of numbers on the right hand side, and
ll
for the list of lists of numbers in the definition
itself.
As in other languages, definitions can be recursive in Joy. In the
first line below is a recursive definition of the factorial function
in one of many variants of conventional notation. In the second line
is a recursive definition in Joy.
factorial(x) = if x = 0 then 1 else x * factorial(x - 1) factorial == [0 =] [pop 1] [dup 1 - factorial *] ifteAgain the Joy version does not use a formal parameter
x
.
It works like this: The definition uses the ifte combinator
immediately after the if-part, the then-part and the else-part have
been pushed.
The ifte
combinator then does this: it executes the
if-part, in this case [0 =]
, which tests whether the
(anonymous) integer parameter is equal to zero. If it is, then the
if-part is executed, in this case [pop 1]
, which pops
the parameter off the stack and replaces it by one. Otherwise the
else-part is executed, in this case [dup 1 - factorial
*]
. This uses dup
to make another copy of the
parameter and subtracts one from the copy. Then the
factorial
function is called recursively on that.
Finally the original parameter and the just computed factorial are
multiplied.
The definition could be shortened and made a little more efficient by using the inbuilt predicate null which tests for zero and the pred operator which takes the predecessor of a number. But these changes are insignificant.
For more complex functions of several arguments it is necessary to be
able to access the arguments anywhere in the definition. Joy avoids
formal parameters altogether, and hence in general arbitrary access
has to be done by mechanisms more sophisticated than dup
,
swap
and pop
.
Here are some more definitions that one might have:
sum == 0 [+] fold product == 1 [*] fold average == [sum] [size] constr12 / concatenation == "" [concat] foldThe last definition is for an operator which yields a single string which is the concatenation of a list of strings.
[ factorial ] mapBut this relies on an external definition of factorial. It was necessary to give that definition explicitly because it is recursive. If one only wanted to compute factorials of lists of numbers, then it would be a minor nuisance to be forced to define factorial explicitly just because the definition is recursive.
A high proportion of recursively defined functions exhibit a very simple pattern: There is some test, the if-part, which determines whether the ground case obtains. If it does, then the non-recursive then-part is executed. Otherwise the recursive else-part has to be executed. In the else-part there is only one recursive call, and there can be something before the recursive call and something after the recursive call. It helps to think of the else-part to have two components, the else1-part before the recursive call, and the else2-part after the recursive call. This pattern is called linear recursion, and it occurs very frequently.
Joy has a useful device, the linrec combinator, which
allows computation of anonymous functions that might have
been defined recursively using a linear recursive pattern. Whereas
the ifte
combinator requires three quoted parameters, the
linrec
combinator requires four: an if-part, a then-part,
an else1-part and an else2-part. For example, the factorial function
could be computed by
[null] [succ] [dup pred] [*] linrecThere is no need for a definition, the above program can be used directly.
Very frequently the if-part of a linear recursion tests for a simple base condition which depends on the type of the parameter. For numbers that condition tends to be being zero, for sets, strings and lists that condition tends to be being empty. The else1-part frequently makes the parameter smaller in some way. For numbers it decrements them, for sets, strings and lists it takes the rest.
Joy has another useful combinator which has the
appropriate if-part and else1-part built in. This is the
primrec combinator, which only has to be supplied with two
quotation parameters, the (modified) then-part and the else2-part of
linear recursion. For the factorial function the two quotation
parameters are very simple:
[1] [*] primreccomputes the factorial function. So, if one wanted to compute the list of factorial of a given list of numbers this can be done by either of the following:
[ [null] [succ] [dup pred] [*] linrec ] map [ [1] [*] primrec ] mapThe factorial of a number is the product of successive natural numbers up to the actual parameter. The following compute instead their sums and the sum of their squares:
[0] [+] primrec [0] [dup * +] primrecMany of the Joy combinators are polymorphic in the sense that they can be applied to parameters of quite different types. The combinator
primrec
can be applied not only to numbers but also to
lists. For example, applied to the list [1 2 3]
the
program
[[]] [[] cons cons] primrecproduces the list
[1 [2 [3 []]]]
. Lisp programmers will
recognise a similarity to "dotted pairs". In the following, the first
turns a set of numbers into a list, the second turns a list of numbers
into a set:
[[]] [cons] primrec [{}] [cons] primrecIn fact, the first can also be applied to a list and the second can also be applied to a set. But in that case they just compute the identity. They can even be applied to numbers - and then they produce a list or a set of numbers from the parameter down to 1.
In many recursive definitions there are two recursive calls of the function being defined. This is the pattern of binary recursion, and it is used in the usual definitions of quicksort and of the Fibonacci function. Joy has a facility that eliminates the need for a recursive definition, the binrec combinator.
The following will quicksort a list whose members can be a
mixture of anything except lists. The program easily fits onto one
line, but for reference it is here written over several numbered
lines:
1 [small] 2 [] 3 [uncons [>] split] 4 [[swap] dip cons concat] 5 binrecThis is how it works: Lines 1..4 each push a quoted program. In line 5 the
binrec
combinator is called, and it will make use
of the four quoted programs and below that the list to be sorted. The
four quoted programs are saved elsewhere, and the binrec
combinator begins by executing the program from line 1. This tests
whether the list to be sorted is small, i.e. has at most one member.
If indeed it is small, then it is sorted already.
The binrec
combinator now executes the program from line
2, which does nothing and hence leaves the small list as it is. On
the other hand, if the list is not small, then the programs in lines 3
and 4 will be executed. The program in line 3 removes the first
element from the list and uses it as a pivot to split the rest of the
list into two sublists, by using the comparison function in
[>]
and the split
combinator.
At this point the binrec
combinator calls itself
recursively on the two sublists and sorts them both. Finally the
program in line 4 combines the two sorted versions and the original
pivot into a single sorted list. The three items are not quite in the
required order, so the [swap] dip
part puts the pivot in
between the two sorted lists.
 Since all operations in the program also work on
strings, the program itself can equally well be used to sort a string.
In fact, the program can be used on sets too, but this of course is pointless. The program is useful, it is part of the Joy system library under the name of qsort.
Many other functions are often defined by recursive definitions that
use binary recursion. In Joy they can all be computed with the
binrec
combinator without the need for a definition. For
example, the following computes the Fibonacci function; it
implements the usual inefficient algorithm:
[small] [] [pred dup pred] [+] binrecThe system library of course contains the well known efficient algorithm.
There are only a few second order combinators, ones which require a
first order combinator as parameter. One of the is treerec
for recursing through trees. These are either anything but a
list, or lists of trees. For example, in the following
treerec
is given [map]
as a parameter, which
in turn will be given [dup *]
as a parameter when
treerec
encounters a list. The function to be applied to
numbers possibly deeply embedded within lists is the squaring function
[dup *]
.
Here is an example:
[ 1 [2 3] [[[4]]] 5 ] [dup *] [map] treerecproduces
[ 1 [2 9] [[[16]]] 25 ]
All of these combinators can be defined in other functional languages, but they are less useful there. This is because their parameters have to be abstractions with variables, and not quotations as in Joy.
Here is an example:
[1 2 3] powerlistproduces as result
[ [1 2 3] [1 2] [1 3] [1] [2 3] [2] [3] [] ]If the ordering does not suit, the result list can always be rearranged, for example it can be reversed. For another example, one can sort the list according to size. The mk_qsort combinator expects an aggregate and a quoted operator as parameters and it applies the operator to each member of the aggregate to use as the basis for sorting them.
[1 2 3] powerlist [size] mk_qsortproduces as a result
[ [] [1] [2] [3] [1 2] [1 3] [2 3] [1 2 3] ]
The powerlist operators can also be applied to a string. The result
is a list of all substrings. In the following the result list is
filtered to retain only those substrings whose size is
greater than 3. This is achieved by the filter
combinator which expects an aggregate and a quoted predicate. The
first line is the program, the second line is the result:
"abcde" powerlist [size 3 >] filter [ "abcde" "abcd" "abce" "abde" "acde" "bcde" ]
The powerlist operators can also be applied to a set. In the program
on the first line below the list of subsets is then filtered to retain
only those of size 3; the result is the list of subsets in the
second line:
{1 2 3 4} powerlist [size 3 =] filter [ {1 2 3} {1 2 4} {1 3 4} {2 3 4} ]
Suppose it is required to find the list, in ascending order, of all
sums of any three distinct numbers taken from a given set of numbers.
We already know how to get the list of all three-membered subsets.
Each should be replaced by its sum, and that can be done with the
map combinator applied to the whole list. The resulting
list of sums then needs to be sorted. The example in the first line
does just that, giving the result in the second line:
{1 2 3 4 5} powerlist [size 3 =] filter [sum] map qsort [6 7 8 8 9 9 10 10 11 12]
In the remainder of this section a small program is to be constructed
which takes one sequence as parameter and returns the list of all
permutations of that sequence. Here is a first draft:
1 If S has only zero or one member 2 then it has only one permutation, so take its unit list 3 else take the first and rest of S, recurse to construct the permutations of the rest 4 insert the first in all positions in all permutations
The recursion pattern is linear, so we can use the linrec
combinator to arrive at this first incomplete program:
1 [ small ] 2 [ unitlist ] 3 [ uncons ] 4 [ "insert the first in all positions in all permutations" ] 5 linrecThe anonymous recursion between steps 3 and 4 will have left a list of permutations of the rest of
S
on top of the stack.
Next, it is necessary to insert the original first of S
into all positions into all these resulting permutations. This
involves replacing each single permutation by a list of permuations
with the original first inserted in all places.
This calls for the map combinator to apply a
constructed program to each permutation. The original first
is currently the second item on the stack. to make it available to
the program to be constructed, it is swap
ped to the top.
The required program consists of a constant part and a variable part.
The constant part now has to be pushed onto the stack. Then the first
is cons
ed into the required program. Then
map
will create a list of list of permutations. But this
is a two-level list, and it should be one-level. So the two level
list has to be flattened to a one-level list.
4.1 [ swap 4.2 [ "the constant part of the program" ] 4.3 cons map 4.4 "flatten the resulting list of lists of sequences" ]
The constant part of the constructed program has to be written next.
The constructed program will be used to map
all
permutations of the rest, and in each case it will begin by pushing
the original first on top of the current permutation being mapped. It
then has to insert this first into all positions of the current
permutation.
This again calls for a linear recursion with linrec. One
way to do this is to give this anonymous recursive function just one
parameter, the current permutation with the original first
swons
in as an initial element. So the task is now to
insert this inital element into all positions in the remainder which
is the current permutation.
<IP_ADDRESS> If the current sequence is small <IP_ADDRESS> then return just its unit list <IP_ADDRESS> else keep 1. a copy 2. its second and 3. the sequence without its second anonymously recurse on 3. <IP_ADDRESS> construct a program to insert the second useSo the constant part 4.2 looks like this:map
to do the insertion usecons
to add the copy from 1.
4.2.1 [ swons <IP_ADDRESS> [ small ] <IP_ADDRESS> [ unitlist ] <IP_ADDRESS> [ dup unswons [uncons] dip swons ] <IP_ADDRESS> [ swap [swons] cons map cons ] <IP_ADDRESS> linrec ]
The only other part that needs to be written is for flattening. This should be trivial by now: If the list is small, then take its unit list else take its first and its rest anonymously recurse on the rest, concatenate the saved first into the result.
Here is the required program:
4.4 [ null ] [ ] [ uncons ] [ concat] linrec
The entire program now is the following:
1 [ small ] 2 [ unitlist ] 3 [ uncons ] 4.1 [ swap 4.2.1 [ swons <IP_ADDRESS> [ small ] <IP_ADDRESS> [ unitlist ] <IP_ADDRESS> [ dup unswons [uncons] dip swons ] <IP_ADDRESS> [ swap [swons] cons map cons ] <IP_ADDRESS> linrec ] 4.3 cons map 4.4 [null] [] [uncons] [concat] linrec ] 5 linrec.
An essentially identical program is in the Joy library under the name permlist. It is considerably shorter than the one given here because it uses two subsidiary programs insertlist and flatten which are useful elsewhere. The program given above is an example of a non-trivial program which uses the linrec combinator three times and the map combinator twice, with constructed programs as parameters on both occasions.
Of course such a program can be written in lambda calculus languages such as Lisp, Scheme, ML or Haskell, but it would need many recursive definitions with attendant named formal parameters.


1 instantiation of ScriptInfo
System.Management.Automation (1)
engine\ScriptInfo.cs (1)
57
ScriptInfo copy = new
ScriptInfo
(this) { IsGetCommandCopy = true, Arguments = argumentList };
9 references to ScriptInfo
System.Management.Automation (9)
engine\CommandDiscovery.cs (2)
605
processor = CreateCommandProcessorForScript((
ScriptInfo
)commandInfo, Context, useLocalScope ?? true, sessionState);
656
private static CommandProcessorBase CreateCommandProcessorForScript(
ScriptInfo
scriptInfo, ExecutionContext context, bool useNewScope, SessionStateInternal sessionState)
engine\GetCommandCommand.cs (2)
1120
ScriptInfo
scriptInfo = info as
ScriptInfo
;
engine\ScriptCommandProcessor.cs (2)
35
this._fromScriptFile = (this.CommandInfo is ExternalScriptInfo || this.CommandInfo is
ScriptInfo
);
261
internal DlrScriptCommandProcessor(
ScriptInfo
scriptInfo, ExecutionContext context, bool useNewScope, SessionStateInternal sessionState)
engine\ScriptInfo.cs (2)
45
internal ScriptInfo(
ScriptInfo
other)
57
ScriptInfo
copy = new ScriptInfo(this) { IsGetCommandCopy = true, Arguments = argumentList };
help\HelpCommands.cs (1)
802
(cmdInfo is ExternalScriptInfo) || (cmdInfo is
ScriptInfo
))


There's an official Google Street View style Pokemon Sword & Shield Wild Area site
Beware of Bewears
by Chris CarterOne of the chief elements of Pokemon Sword & Shield that has me the most excited is undoubtedly the Wild Area.
Billed as an open MMO-like space, players can roam around this gigantic zone and capture Pokemon, as well as meetup and take on raid battles. Given that some creatures can't be caught right away until you have a certain number of gym badges it'll serve as one of the endgame activities of the new generation. Provided that it's large and varied enough, I'm excited to spend some time in it.
Ahead of launch, Game Freak put out an official site of sorts just for the Wild Area, which is crafted like a Google Street View app. It's in Japanese right now, but you can explore a rudimentary re-creation of the zone, and click on Pokemon for info and an evolution gallery. Remember, the Wild Area is going to take up a huge portion of the entire Galar region map.
It's cute! Hopefully the real Wild Area will be this vibrant, and take advantage of the extra power of the Switch as the mainline (non-spinoff) series moves to consoles for the first time.
Wild Area Search [Pokemon]


Basic Form Elements
Form Features
Dashboard
Basic Form Elements
Basic Form Controls
Select a country
Radio Buttons
Radio 1
Radio 2
Radio Disabled
Disabled Selects
1
2
3
4
5


Popular Areas in how to order a phone book
Verizon to end distribution of residential phone books ...
Jul 11, 2011 . The new phone book soon won't be here. Verizon . Customers will be able to order free residential print and CD-ROM versions of white pages .
http://hamptonroads.com/2011/07/verizon-end-distribution-residential-phone-books
Commonwealth Telephone Directory - Department of General ...
To order the 2012 Commonwealth Telephone Directory, agencies must do so through PAPublisher at www.papublisher.state.pa.us. If you are not registered .
http://www.portal.state.pa.us/portal/server.pt/community/telephone_directory/1295
How do I Order a Phone Book? - Answers.Ask.com
You can order a phone book by calling your local phone company and requesting one. Generally they will deliver them to your residence when a... view more.
http://answers.ask.com/Consumer_Electronics/Phone_and_PDA/how_do_i_order_a_phone_book
Order or adjust the number of printed phone books you receive - AT&T
Learn the answer to: Order or adjust the number of printed phone books you receive (White/Yellow Pages)
http://www.att.com/esupport/article.jsp?sid=KB403108&cv=807&title=Order%20or%20adjust%20the%20number%20of%20printed%20phone%20books%20you%20receive%20(White/Yellow%20Pages)
Any place that sells phone books? (Las Vegas: fit in, buying ...
Nov 26, 2010 . I know you locals get them free, but I need a Las Vegas phone book but . Are there any local places that I might be able to order one from and .
http://www.city-data.com/forum/las-vegas/1138573-any-place-sells-phone-books-las.html
Advertising Solutions - Login
Reach consumers searching for what you sell; Access valuable ad performance data; Easy to sign up, set up and manage; Save time by paying online. Already .
http://adsolutions.yp.com/SSO/Login


{% extends "base.html" %} {% block title %}Heroku Python TOTP Demo{% endblock %} {% block pagetitle %}Python TOTP Demo{% endblock %} {% block content %}
This simple app demonstrates the Time-Based One-Time Password (TOTP) algorithm by allowing very simple creation and authentication of users. For the purposes of this app, authentication is done only using a username and a one-time password generated using Google Authenticator or another TOTP-enabled client. Note that I skipped passwords entirely, but in real world applications one-time passwords are almost always the second factor, the first being a user chosen password.


Back Step 6 of 6
Do you want to start your appeal now?
Your appeal to the tax tribunal will cost £20
What are fees for?
- your fees are paid to HM Courts and Tribunals Service (HMCTS) towards the cost of an independent judgement
- you may have to pay further fees depending on your case and whether it needs a hearing
- all tax tribunal fees will be refunded by HMRC (or other government agency) if your appeal is successful
- if you’re on a low income or receiving certain benefits, you should first apply for help with fees
What you'll need
- your name and address (and your representative’s if you have one)
- copy of the review decision letter from HMRC to upload (e.g. a scan or PDF)
- details of your dispute, why you’re appealing and the result you want
- credit or debit card to pay your appeal fee
What happens next
You can start your appeal by entering your details. You'll be able to save your appeal information and return later to complete everything and pay your fee.
What did you think of this service? (takes 30 seconds)


Preparation time
30 mins to 1 hour
Cooking time
30 mins to 1 hour
Serves
Serves 4
Duck works really well with Chinese five-spice, and this is such an easy way to cook it. Just drop the complicated sauce and presentation if you're short of time.
Preheat the oven to 200C/400F/Gas 4.
For the duck sauce, place the duck carcasses in a roasting tray and cook in the oven for 20-30 minutes. Just before they finish roasting, sprinkle the bones with the Chinese five-spice.
Remove the carcasses from the oven and place over a low heat on the hob. Add the onions and garlic. Cook until the onions are translucent and just starting to colour. Add the thyme.
Remove the bones and set them aside to cool. Deglaze the roasting tin with the chicken stock. Set aside
In a saucepan, bring the honey to a rolling boil and cook for three minutes (be careful not to burn the honey as it will make the sauce bitter). Add the vinegar and cook until the volume of liquid has reduced by a third.
Add the cooled duck carcasses and chicken stock to the pan, along with the veal stock, peppercorns and cream. Bring to the boil and skim off the scum from the surface. Reduce the heat to a simmer and cook for 30 minutes.
Strain the sauce through a colander and then pass through a fine sieve to remove any fragments of bone. Return to the pan, bring to the boil and cook until reduced to a sauce consistency. Season with salt.
For the duck breasts, using a sharp knife score the fatty skin of the duck breast in a criss-cross pattern, but be careful not to cut the meat. Season with salt and pepper.
Heat a little oil in a heavy-bottomed frying pan and add the duck breasts skin-side down. Cook at a fairly high temperature so that the skin renders out the fat, but take care not to burn the skin.
When the skin is golden-brown and crisp, turn the breast over and cook the other side for a minute before returning it once more to its skin side. Crisp the skin a little more before turning the breast onto its other side again and finish cooking to your liking.
Meanwhile, put the garlic cloves in a pan of cold water and bring to the boil, refresh in cold running water and repeat twice more.
Once the duck is cooked, remove it from the pan and brush the honey and five-spice over the crisp skin. Set aside in a warm place to rest before serving.
Place the garlic cloves in a heavy-bottomed pan with a little butter and season with salt and pepper. Cook slowly until soft and lightly golden-brown then add the blanched celeriac into the pan to warm through.
For the savoy cabbage, add the cabbage to a pan of boiling salted water and cook until tender (about 3-4 minutes). Refresh in ice-cold water. Drain well and pat dry.
In a frying pan, gently fry the finely chopped shallots in the butter until translucent, then add the smoked bacon. Add the cooked cabbage and cook until dry and the bacon is crisp. Stir in the garlic purée and season, to taste, with salt and pepper.
To serve, heat the butter small frying pan and, once hot, add the mushrooms and gently fry for a minute.
If necessary, reheat the duck in a low oven for a few minutes, and then slice thinly. Place the cabbage down the middle of the serving plates and place the duck on top. Add the celeriac and garlic around the outside of the duck and then pour over the sauce.


This Package contains the basic components of the SPICE3 models. The first letter of the
name of the component shows the SPICE name, e.g., R_Resistor: R is the SPICE-name of the component
resistor which is used in SPICE-Netlists.
| Name | Description |
|---|---|
| Ground | Ground node |
| R_Resistor | Ideal linear electrical resistor |
| C_Capacitor | Ideal linear electrical capacitor |
| L_Inductor | Ideal linear electrical inductor |
| K_CoupledInductors | Inductive coupling via coupling factor K |
| E_VCV | Linear voltage-controlled voltage source |
| G_VCC | Linear voltage-controlled current source |
| H_CCV | Linear current-controlled voltage source |
| F_CCC | Linear current-controlled current source |


/home/david/GitProjects/h5pp/h5pp/include/h5pp/h5pp.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppConstants.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppDimensionType.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppEigen.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppEnums.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppFile.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppFilesystem.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppFormat.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppHdf5.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppHid.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppHyperslab.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppInfo.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppLogger.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppOptional.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppPropertyLists.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppScan.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppSpdlog.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppTypeCompound.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppTypeCompoundCreate.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppTypeSfinae.h
/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppUtils.h


| 2678 - Subsequence Europe - Southeastern - 2006/2007 | |||||
| Submit | Ranking |
A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.
Many test cases will be given. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.
For each the case the program has to print the result on separate line of the output file. If there isn't such a subsequence, print 0 on a line by itself.
10 15 5 1 3 5 10 7 4 9 2 8 5 11 1 2 3 4 5
2 3


|
Inventory Grid
an inventory grid similar to diablo
|
Classes | |
| class | Board |
| manager for the inventory board/grid More... | |
| class | BoardSlot |
| defines a board/grid slot More... | |
| class | BoardPreview |
| helper for preview More... | |
| class | InventoryGrid |
| the board/grid data More... | |
| class | EquippedGear |
| manager for the equipment More... | |
| class | GearSlot |
| defines a gear slot More... | |
| class | InventoryPiece |
| defines an inventory piece More... | |
| class | EquippedGear_UI |
| example UI class that uses the EquippedGear class and subs to GridInventory_UI More... | |
| class | GridInventory_UI |
| ui example using Board class to generate the inventory grid/board More... | |
| class | PretendItem |
| pretend item, used for the demo scene on buttons to create new pieces to add to inventory More... | |
| class | Pattern |
| defines an item's grid pattern on the board More... | |
| class | PatternHolder |
| holds the pattern class to make scriptables out of them More... | |
| class | VirtualInventoryCell |
| defines an inventory cell/slot More... | |
Enumerations | |
| enum class | PatternAlignment { Vertical = 0 , Horizontal = 10 } |
| experimental, in theory should work More... | |
|
strong |


| public nothrow | Date() |
| public nothrow | Date(short year_, Month month_, sbyte day_) |
| public nothrow Date | AddDays(int n) |
| public nothrow Date | AddMonths(int n) |
| public nothrow Date | AddYears(short n) |
| public inline nothrow sbyte | Day() const |
| public inline nothrow Month | GetMonth() const |
| public nothrow String<char> | ToString() const |
| public nothrow String<char> | ToString(bool omitDashes) const |
| public inline nothrow short | Year() const |
| private sbyte | day |
| private Month | month |
| private short | year |


function [X, fX, i] = minimize(X, f, length, varargin) % Minimize a differentiable multivariate function using conjugate gradients. % % Usage: [X, fX, i] = minimize(X, f, length, P1, P2, P3, ... ) % % X initial guess; may be of any type, including struct and cell array % f the name or pointer to the function to be minimized. The function % f must return two arguments, the value of the function, and it's % partial derivatives wrt the elements of X. The partial derivative % must have the same type as X. % length length of the run; if it is positive, it gives the maximum number of % line searches, if negative its absolute gives the maximum allowed % number of function evaluations. Optionally, length can have a second % component, which will indicate the reduction in function value to be % expected in the first line-search (defaults to 1.0). % P1, P2, ... parameters are passed to the function f. % % X the returned solution % fX vector of function values indicating progress made % i number of iterations (line searches or function evaluations, % depending on the sign of "length") used at termination. % % The function returns when either its length is up, or if no further progress % can be made (ie, we are at a (local) minimum, or so close that due to % numerical problems, we cannot get any closer). NOTE: If the function % terminates within a few iterations, it could be an indication that the % function values and derivatives are not consistent (ie, there may be a bug in % the implementation of your "f" function). % % The Polack-Ribiere flavour of conjugate gradients is used to compute search % directions, and a line search using quadratic and cubic polynomial % approximations and the Wolfe-Powell stopping criteria is used together with % the slope ratio method for guessing initial step sizes. Additionally a bunch % of checks are made to make sure that exploration is taking place and that % extrapolation will not be unboundedly large. % % See also: checkgrad % % Copyright (C) 2001 - 2010 by Carl Edward Rasmussen, 2010-01-03 INT = 0.1; % don't reevaluate within 0.1 of the limit of the current bracket EXT = 3.0; % extrapolate maximum 3 times the current step-size MAX = 20; % max 20 function evaluations per line search RATIO = 10; % maximum allowed slope ratio SIG = 0.1; RHO = SIG/2; % SIG and RHO are the constants controlling the Wolfe- % Powell conditions. SIG is the maximum allowed absolute ratio between % previous and new slopes (derivatives in the search direction), thus setting % SIG to low (positive) values forces higher precision in the line-searches. % RHO is the minimum allowed fraction of the expected (from the slope at the % initial point in the linesearch). Constants must satisfy 0 < RHO < SIG < 1. % Tuning of SIG (depending on the nature of the function to be optimized) may % speed up the minimization; it is probably not worth playing much with RHO. % The code falls naturally into 3 parts, after the initial line search is % started in the direction of steepest descent. 1) we first enter a while loop % which uses point 1 (p1) and (p2) to compute an extrapolation (p3), until we % have extrapolated far enough (Wolfe-Powell conditions). 2) if necessary, we % enter the second loop which takes p2, p3 and p4 chooses the subinterval % containing a (local) minimum, and interpolates it, unil an acceptable point % is found (Wolfe-Powell conditions). Note, that points are always maintained % in order p0 <= p1 <= p2 < p3 < p4. 3) compute a new search direction using % conjugate gradients (Polack-Ribiere flavour), or revert to steepest if there % was a problem in the previous line-search. Return the best value so far, if % two consecutive line-searches fail, or whenever we run out of function % evaluations or line-searches. During extrapolation, the "f" function may fail % either with an error or returning Nan or Inf, and minimize should handle this % gracefully. if max(size(length)) == 2, red=length(2); length=length(1); else red=1; end if length>0, S='Linesearch'; else S='Function evaluation'; end i = 0; % zero the run length counter ls_failed = 0; % no previous line search has failed [f0 df0] = feval(f, X, varargin{:}); % get function value and gradient Z = X; X = unwrap(X); df0 = unwrap(df0); %fprintf('%s %6i; Value %4.6e\r', S, i, f0); if exist('fflush','builtin') fflush(stdout); end fX = f0; i = i + (length<0); % count epochs?! s = -df0; d0 = -s'*s; % initial search direction (steepest) and slope x3 = red/(1-d0); % initial step is red/(|s|+1) while i < abs(length) % while not finished i = i + (length>0); % count iterations?! X0 = X; F0 = f0; dF0 = df0; % make a copy of current values if length>0, M = MAX; else M = min(MAX, -length-i); end while 1 % keep extrapolating as long as necessary x2 = 0; f2 = f0; d2 = d0; f3 = f0; df3 = df0; success = 0; while ~success && M > 0 try M = M - 1; i = i + (length<0); % count epochs?! [f3 df3] = feval(f, rewrap(Z,X+x3*s), varargin{:}); df3 = unwrap(df3); if isnan(f3) || isinf(f3) || any(isnan(df3)+isinf(df3)), error(''), end success = 1; catch % catch any error which occured in f x3 = (x2+x3)/2; % bisect and try again end end if f3 < F0, X0 = X+x3*s; F0 = f3; dF0 = df3; end % keep best values d3 = df3'*s; % new slope if d3 > SIG*d0 || f3 > f0+x3*RHO*d0 || M == 0 % are we done extrapolating? break end x1 = x2; f1 = f2; d1 = d2; % move point 2 to point 1 x2 = x3; f2 = f3; d2 = d3; % move point 3 to point 2 A = 6*(f1-f2)+3*(d2+d1)*(x2-x1); % make cubic extrapolation B = 3*(f2-f1)-(2*d1+d2)*(x2-x1); x3 = x1-d1*(x2-x1)^2/(B+sqrt(B*B-A*d1*(x2-x1))); % num. error possible, ok! if ~isreal(x3) || isnan(x3) || isinf(x3) || x3 < 0 % num prob | wrong sign? x3 = x2*EXT; % extrapolate maximum amount elseif x3 > x2*EXT % new point beyond extrapolation limit? x3 = x2*EXT; % extrapolate maximum amount elseif x3 < x2+INT*(x2-x1) % new point too close to previous point? x3 = x2+INT*(x2-x1); end end % end extrapolation while (abs(d3) > -SIG*d0 || f3 > f0+x3*RHO*d0) && M > 0 % keep interpolating if d3 > 0 || f3 > f0+x3*RHO*d0 % choose subinterval x4 = x3; f4 = f3; d4 = d3; % move point 3 to point 4 else x2 = x3; f2 = f3; d2 = d3; % move point 3 to point 2 end if f4 > f0 x3 = x2-(0.5*d2*(x4-x2)^2)/(f4-f2-d2*(x4-x2)); % quadratic interpolation else A = 6*(f2-f4)/(x4-x2)+3*(d4+d2); % cubic interpolation B = 3*(f4-f2)-(2*d2+d4)*(x4-x2); x3 = x2+(sqrt(B*B-A*d2*(x4-x2)^2)-B)/A; % num. error possible, ok! end if isnan(x3) || isinf(x3) x3 = (x2+x4)/2; % if we had a numerical problem then bisect end x3 = max(min(x3, x4-INT*(x4-x2)),x2+INT*(x4-x2)); % don't accept too close [f3 df3] = feval(f, rewrap(Z,X+x3*s), varargin{:}); df3 = unwrap(df3); if f3 < F0, X0 = X+x3*s; F0 = f3; dF0 = df3; end % keep best values M = M - 1; i = i + (length<0); % count epochs?! d3 = df3'*s; % new slope end % end interpolation if abs(d3) < -SIG*d0 && f3 < f0+x3*RHO*d0 % if line search succeeded X = X+x3*s; f0 = f3; fX = [fX' f0]'; % update variables %fprintf('%s %6i; Value %4.6e\r', S, i, f0); if exist('fflush','builtin') fflush(stdout); end s = (df3'*df3-df0'*df3)/(df0'*df0)*s - df3; % Polack-Ribiere CG direction df0 = df3; % swap derivatives d3 = d0; d0 = df0'*s; if d0 > 0 % new slope must be negative s = -df0; d0 = -s'*s; % otherwise use steepest direction end x3 = x3 * min(RATIO, d3/(d0-realmin)); % slope ratio but max RATIO ls_failed = 0; % this line search did not fail else X = X0; f0 = F0; df0 = dF0; % restore best point so far if ls_failed || i > abs(length) % line search failed twice in a row break; % or we ran out of time, so we give up end s = -df0; d0 = -s'*s; % try steepest x3 = 1/(1-d0); ls_failed = 1; % this line search failed end end X = rewrap(Z,X); fprintf('\n'); if exist('fflush','builtin') fflush(stdout); end function v = unwrap(s) % Extract the numerical values from "s" into the column vector "v". The % variable "s" can be of any type, including struct and cell array. % Non-numerical elements are ignored. See also the reverse rewrap.m. v = []; if isnumeric(s) v = s(:); % numeric values are recast to column vector elseif isstruct(s) v = unwrap(struct2cell(orderfields(s))); % alphabetize, conv to cell, recurse elseif iscell(s) for i = 1:numel(s) % cell array elements are handled sequentially v = [v; unwrap(s{i})]; end end % other types are ignored function [s v] = rewrap(s, v) % Map the numerical elements in the vector "v" onto the variables "s" which can % be of any type. The number of numerical elements must match; on exit "v" % should be empty. Non-numerical entries are just copied. See also unwrap.m. if isnumeric(s) if numel(v) < numel(s) error('The vector for conversion contains too few elements') end s = reshape(v(1:numel(s)), size(s)); % numeric values are reshaped v = v(numel(s)+1:end); % remaining arguments passed on elseif isstruct(s) [s p] = orderfields(s); p(p) = 1:numel(p); % alphabetize, store ordering [t v] = rewrap(struct2cell(s), v); % convert to cell, recurse s = orderfields(cell2struct(t,fieldnames(s),1),p); % conv to struct, reorder elseif iscell(s) for i = 1:numel(s) % cell array elements are handled sequentially [s{i} v] = rewrap(s{i}, v); end end % other types are not processed


Track Counts = {}
Old count of track #2 = [0]
Now count of track #2 = [1]
Playing track #[2]: Lucy in the Sky with Diamonds
Track Counts = {2=1}
Old count of track #0 = [0]
Now count of track #0 = [1]
Playing track #[0]: Sgt. Pepper's Lonely Hearts Club Band
Track Counts = {0=1, 2=1}
Old count of track #4 = [0]
Now count of track #4 = [1]
Playing track #[4]: Fixing a Hole
Track Counts = {0=1, 2=1, 4=1}
Old count of track #3 = [0]
Now count of track #3 = [1]
Playing track #[3]: Getting Better
Track Counts = {0=1, 2=1, 3=1, 4=1}
Old count of track #2 = [1]
Now count of track #2 = [2]
Playing track #[2]: Lucy in the Sky with Diamonds
Track Counts = {0=1, 2=2, 3=1, 4=1}
Old count of track #3 = [1]
Now count of track #3 = [2]
Playing track #[3]: Getting Better
Track Counts = {0=1, 2=2, 3=2, 4=1}
Old count of track #1 = [0]
Now count of track #1 = [1]
Playing track #[1]: With a Little Help from My Friends
Track Counts = {0=1, 1=1, 2=2, 3=2, 4=1}
Old count of track #3 = [2]
Now count of track #3 = [3]
Playing track #[3]: Getting Better
Track Counts = {0=1, 1=1, 2=2, 3=3, 4=1}
Old count of track #3 = [3]
Now count of track #3 = [4]
Playing track #[3]: Getting Better
Track Counts = {0=1, 1=1, 2=2, 3=4, 4=1}
Old count of track #4 = [1]
Now count of track #4 = [2]
Playing track #[4]: Fixing a Hole
Track Counter = {0=1, 1=1, 2=2, 3=4, 4=2}
Track #0 played [1] times.
Track #1 played [1] times.
Track #2 played [2] times.
Track #3 played [4] times.
Track #4 played [2] times.


Heaven of island
By VIPUL PHULWANIHave you ever been to a place or country where you can experience almost everything, yes everything Whether it's daily street chaos or never-forgotten street food, where anyone on diet can’t deny eating delicious food in a restaurant or at someone’s home, where you have a wide range of cuisines, where you have six seasons, Where there is saying that every 100km food changes, language changes, culture changes.
 Well this is not Mauritius or Malaysia nor Indonesia nor US nor Thailand, THIS IS INDIA.
If I ask you to name a place where you can experience oceanic life and no doubt beautiful beaches, it’s a 90% of chance that you will name goa. But if I ask you for the very less crowded beach with less or no network connection where smartphones and other gadgets are of no use and where you are in love with nature. Don’t know. Let me take you there.
WELCOME TO ANDAMAN AND NICOBAR ISLAND
Andaman and Nicobar Islands, also known as Kalapani is one of the most beautiful places you can visit in India.
They include a whooping 572 islands in total out of which only 50 are inhabited by people.
The islands have been the favorite tourist destination for a while now and offer one of the most out-of-world, exquisite vacation spots in India.
The weather here is moderate and doesn't follow the trends of India. When there is summer all over the mainland, Andamans just start out with monsoon and therefore offer perfect break from the harsh sun.
The glistening clean white sand beaches, wide shorelines and crystal blue waters offer a perfect place to take a dip or enjoy water sports throughout the day.
Destinations
- Havelock Island
- Port Blair
- Jolly Buoy
- North Bay
- Neil Island
- Ross Island
- Baratang
- Cinque Island
- Diglipur
- Red Skin Island
- Mayabunder
- Barren Island
Museums and Historical Attractions
- Cellular Jail
- Samudrika Museum
- Anthropological Museum
- Fisheries Museum
- Chatham Saw Mill
Water Sports
- Scuba Diving
- Sea Kart
- Parasailing
- Sea Walk
- Snorkeling
- Semi Submarine
- Glass Boats
- Jet Skiing
- Sofa Ride
- Banana Ride
- Game Fishing
- Kayaking


JUNE 21 St Aloysius Gonzaga, religious
(1568-1591).
An Italian Jesuit of a noble family, he died as a result of his devoted and
heroic nursing of the plague-stricken.
ENTRANCE ANTIPHON
The clean of hands and pure of heart shall climb the mountain of the Lord and stand in his holy place.
COLLECT
O God, giver of heavenly gifts, who in Saint Aloysius Gonzaga joined penitence to a wonderful innocence of life, grant, through his merits and intercession, that, though we have failed to follow him in innocence, we may imitate him in penitence. Through our Lord Jesus Christ, your Son, who lives and reigns with you in the unity of the Holy Spirit, one God, for ever and ever.
PRAYER OVER THE OFFERINGS
Grant us, O Lord, that by the example of Saint Aloysius, we may take our place at the heavenly banquet, clothed always in our wedding garment, so that, by participation in this mystery, we may possess the riches of your grace. Through Christ our Lord.
PREFACE of Holy Men & Women
or Virgins & Religious
COMMUNION ANTIPHON
God gave them bread from heaven; man ate the bread of Angels.
PRAYER AFTER COMMUNION
Bring us, who
have been fed with the food of Angels, O Lord, to serve you in purity of life,
and, following the example of Saint Aloysius, whom we honour today, may we
persevere in constant thanksgiving. Through Christ our Lord.


| DOSE: |
4 Tbsp |
smoked |
Nutmeg |
(powder / crystals) |
Well I had recently heard about how smoking nutmeg will make you trip, so I got the bright idea to try it. I smoked about 2 tbspns of the stuff at about 7 at night. After some how choking that stuff down I sat on my bed waiting for the fun to start. After about 30 min. I started to develope a raging headache, so I figured maybe I hadn't smoked enough so I smoked another 2 tbsps.
By this time my lungs felt like I'd smoked a pack and a half of unfiltered Lucky Strikes. I found that not only had my headache not ceased and my lungs felt like shit, but I also felt like vomiting. Finally about two hours later( and four aspirin later) my headache was gone.  I decked my friend for his bright idea)
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


This is a simple example of using non-destructive filtering to adjust what is displayed in a spry:region based on user input.
Enter the name of a state: Contains:
Matching States ({ds_RowCount} of {ds_UnfilteredRowCount}):


My name is Anjali Jayan and I am the creator of this website. I would like to thank my family, especially my mom, for inspiring my passion about medicine. She is an oncologist who is always devoted to her amiable patients. I am also dedicating my website to my mother's patients because breast cancer is an issue that needs to be more aware to the public. Furthermore, I want to acknowledge Girls Who Code and their staff for helping me whenever I needed assistance in code. They have taught me numerous computer coding languages, while making the coding class an entertaining experience. Thank you for all of the support.  American Cancer Society, Susan G Komen, National Breast Cancer Foundation, and BreastCancer.org provided me fascinating facts about the science of breast cancer.


#include <vqec_channel_private.h>
Data Fields | |
| uint32_t | upcall_last_generation_num |
| uint32_t | upcall_events |
| uint32_t | upcall_lost_events |
| uint32_t | upcall_repeat_events |
| uint32_t | upcall_error_events |
| uint32_t | upcall_ack_inputs |
| uint32_t | upcall_ack_nulls |
| uint32_t | upcall_ack_errors |
| uint32_t | dp_generation_id |
Dataplane generation Id for channel (last cached value).
Data acknowledgment messages that were malformed / in-error.
IRQ data acknowledgments received.
IRQ data acknowledgments that were null.
Error event count.
Upcall event counter.
Last received generation number.
Lost event count.
Repeated or out-of-order event count.


Find your Vacation Destination!
It's Friday night: What are your Plans?
Dinner & a movie
Bonfire with friends
Hiking
Wine Tasting
What's your favorite food?
Pizza
Protein bar
Charcuterie
Seafood
What activity would you rather do?
Hang out at the beach.
Checkout a broadway show
Rock Climbing
Visit a Museum
What lodging accomodations do you Prefer?
Hostel
Five Star Hotel
Beach House
Under the stars
You would describe yourself Personality as:
Outgoing
Adventerous
Romantic
Relaxed
A good Experience:
Lively
Peaceful
Adrenaline Rush
Cultured
Submit Answers
×


Install the LAMP Stack
This approach uses tasksel. Tasksel should only be used during initial setup of a server and not for ongoing maintenance and configuration. It installs all of the software and configurations required for a specific task.
-
sudo apt-get update
-
sudo apt-get install tasksel
-
sudo tasksel
-
Check LAMP server
-
Enter new MySQL root password when asked
-
Test the LAMP
Test Apache
-
Browse to your ip_address or hostname (servername) to view the default Apache page
-
Enable mod_rewite (needed for WordPress)
-
sudo a2enmod rewrite
-
service apache2 restart
-
Test PHP
-
sudo nano /var/www/html/phpinfo.php
-
Add
<?php phpinfo(); ?>
-
Save
-
Browse to servername/phpinfo.php
-
-
Once it is working, remove the phpinfo.php file for security disclosure reasons.
-
sudo rm /var/www/html/phpinfo.php
-
Test MySQL
An easy way to test MySQL is to install phpMyAdmin.
-
sudo apt-get install phpmyadmin php-gettext
-
Browse to servername/phpmyadmin
-
Login with root and the password you set earlier
Test a Virtual Host
A virtual host on Apache allows Apache to serve websites for multiple domains of a single IP address or interface. I’ll demonstrated this using a simple configuration for the atest.com domain.
-
Review the default config,
less /etc/apache2/sites-available/000-default.conf
-
sudo nano /etc/apache2/sites-available/atest.com.conf
-
Add the following to this new configuration
# start atest.COM
<VirtualHost *:80>
ServerName atest.com
ServerAlias *.atest.com
ServerAdmin<EMAIL_ADDRESS>DocumentRoot /var/www/atest.com/html
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/atest.com/html/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
</VirtualHost>
# end atest.COM
-
Note the DocumentRoot is /var/www/atest.com/html. This is where all the website files will go.
-
Create a web viewable file
-
sudo nano /var/www/atest.com/html/index.html
-

<title>Welcome to A Test!</title>

Success! This is a test page of the atest.com virtual host settings.

-
Change file permissions of web accessible files. (Caution: this disables all executable files)
-
sudo chmod -R 644 /var/www
-
sudo chmod -R ug=rwX,o=rX /var/www
-
-
Enable the virtual host,
sudo a2ensite atest.com.conf
-
to disable a site use `sudo a2dissite atest.com.conf `
-
-
service apache2 reload
Next, is to point the domain at the server’s IP address. This is not covered in this document but there are two methods.
-
Use the hosts file
-
/etc/hosts on Linux
-
C:\\Windows\\System32\\drivers\\etc\\hosts on Windows
-
-
Set your domain using DNS. This could be your domain registrar or a third party like DNS Made Easy.
Install WordPress
I prefer not to use the apt system for installing and maintaining WordPress. This application has frequent updates some of which may be critical, so install it from [WordPress](https://wordpress.org/download/) and enable automatic updates. This example uses the amaker.com domain.
Set your DNS or hosts file to point your domain to the server
-
sudo mkdir /var/www/amaker.com
-
sudo cd /var/www/amaker.com
-
sudo wget "https://wordpress.org/latest.tar.gz"
-
sudo tar -xzvf latest.tar.gz
-
Use WordPress as the root for amaker.com
-
sudo mv wordpress html
-
-
WordPress itself will need to modify files for configuration and updates
-
sudo chown -R www-data:www-data html
-
Configure a Virtual Host
-
Similar to the previous virtual host except that now we must permit mod_rewrite and .htaccess files.
-
sudo nano /etc/apache2/sites-available/amaker.com.conf
-
-
Add the following to this new configuration
# start amaker.COM
<VirtualHost *:80>
ServerName amaker.com
ServerAlias *.amaker.com
ServerAdmin<EMAIL_ADDRESS>DocumentRoot /var/www/amaker.com/html
<Directory /var/www/amaker.com/html>
Options -Indexes +FollowSymLinks +MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
</VirtualHost>
# end amaker.COM
-
sudo a2ensite amaker.com.conf
-
sudo service apache2 restart
Add a database
Here we will add a user and database to be used by our WordPress installation. For this example the user and database are named amaker.
-
Login to phpMyAdmin
-
Click the User Accounts tab
-
Add a new user
-
Make certain to check the box Create database with same name and grant all privileges
-
Configure WordPress
The configuration is now completed mostly via browser.
-
Browse to servername
-
Follow the prompts and enter the required information
-
Login and browse your new WordPress site
Backup WordPress Files
Backing up files is an important task in maintaining and recovering your WordPress site. Plugins are available to help with this task but I prefer to automate this task with scripts. First, I will run through the manual process and then share the scripts.
Assumptions:
-
WordPress sites are located in /var/www. This example uses the site test.
-
Git cloned repositories are located at /var/local/repos. The example site uses test.
-
Offsite backup is stored to an AWS S3 bucket. This example uses bucket-repos
Manual Initializing Run
Git and Clone the Site
-
sudo -i
-
cd /var/www/test
-
git init /var/www/test
-
git add --all
-
git commit -m "Initial commit of site"
-
mkdir /var/local/repos
-
git clone /var/www/test /var/local/repos/test
-
exit
| Since some files contain sensitive information (particularly wp-config.php), the clone should not be public. |
Sync the Clone to AWS S3
You now have a local clone of your current WordPress files. Now lets sync the clone to AWS S3. This method uses AWS CLI, see more at https://aws.amazon.com/documentation/cli/.
-
Install awscli
-
sudo apt install python-pip
-
sudo pip install awscli
-
-
Configure awscli,
aws configure
-
You need your AWS Access Key and Secret Access key.
-
If you don’t have those keys, see https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html
-
Some of the python scripts also make use of boto3. See https://github.com/boto/boto3 and https://boto3.readthedocs.io/en/latest/.
-
Install boto3
-
sudo pip install boto3
-
-
Since we have already configured AWS CLI, boto3 is already configured also.
Setup the S3 bucket
-
Make a new bucket,
aws s3 mb s3://bucket-repos
-
List all buckets,
aws s3 ls
-
List the contents of a bucket,
aws s3 ls s3://bucket-repos
Synchronize the contents of the local repository with the S3 bucket.
-
sudo aws s3 sync /var/local/repos/test s3://bucket-repos/test --delete
-
Verify,
aws s3 ls s3://bucket-repos/test/html/
Creating a Scripted Initializing Run
Now let’s automate that whole process by creating a shell script. First we’ll create some text files that are used as input to the script. All of the text files are most easily created automatically, though each may be edited manually. The text files hold one site name per line.
Already Initialized Sites
The first file is s3ed_sites.txt. This is a list of sites already run through this process. The entries are auto-generated using the following make_s3ed.py script. Call the script with python make_s3ed.py > s3ed_sites.txt
#!/bin/python
"""
make_s3ed.py: Connects to S3 bucket used for repositories to list all currently synced sites. The output is often piped to s3ed_sites.txt
How to call:
python make_s3ed.py > s3ed_sites.txt
"""
import boto3
S3BUCKET = "ggis-repos"
client = boto3.client('s3')
paginator = client.get_paginator('list_objects')
result = paginator.paginate(Bucket=S3BUCKET, Delimiter='/')
for prefix in result.search('CommonPrefixes'):
print(prefix.get('Prefix')[:-1])
All Sites
The second file is all_sites.txt, a list of all sites in /var/www that need to be initialized. This can be auto-generated by using a command such as ls /var/www > all_sites.txt
.
ToDo Sites
The third file is todo_sites.txt. This file is just the difference between s3ed_sites.txt and all_sites.txt. The following python script, all-s3ed.py, creates this third file. Call the script by python ./all-s3ed.py
#!/bin/python
"""
all-s3ed.py: Generates the set difference to create the todo_sites file.
"""
file1 = "s3ed_sites.txt"
file2 = "all_sites.txt"
file3 = "todo_sites.txt"
with open(file1) as f:
done = f.read().splitlines()
with open(file2) as f:
all = f.read().splitlines()
todo = set(all).difference(done)
with open(file3, 'w') as f:
f.write('\n'.join(todo))
All Sites Intersection With S3 Sites
A list of sites that are available on the server and are also synced to S3 will be needed. The python script make_all_intersect_s3.py_ is piped to create the file all_intersect_s3.txt. Call it with python make_all_intersect_s3.py > all_intersect_s3.txt
#!/bin/python
"""
make_all_join_s3.py: Generates the set intersect to prints the file list.
"""
file1 = "s3ed_sites.txt"
file2 = "all_sites.txt"
with open(file1) as f:
done = f.read().splitlines()
with open(file2) as f:
all = f.read().splitlines()
intersect = set(all).intersection(done)
for item in intersect:
print(item)
Perform the Initial Git and Sync to S3
Now we use a bash script to control the flow and call various commands. The script is init_git_then_s3.sh. This file is called by sudo ./init_git_then_s3.sh $(cat todo_sites.txt)
#!/bin/bash
#
# This script must be run as sudo.
# This script expects site names input from a file.
# Call this script thusly:
# sudo ./init_git_then_s3.sh $(cat todo_sites.txt)
# Some variables that you may choose to change.
SITEDIR="/var/www/"
REPOSDIR="/var/local/repos/"
S3BUCKET="ggis-repos"
SITES="$@"
for f in $SITES
do
cd $SITEDIR$f
git init $SITEDIR$f
git add --all
git commit -m "Initial commit of site"
git clone $SITEDIR$f $REPOSDIR$f
aws s3 sync $REPOSDIR$f s3://$S3BUCKET/$f --delete
done
Performing the Initializing Run
Let’s put it all together.
-
python make_s3ed.py > s3ed_sites.txt
-
ls /var/www > all_sites.txt
-
python ./all-s3ed.py
-
sudo ./init_git_then_s3.sh $(cat todo_sites.txt)
-
Manually verify that all that your sites are now synced to S3.
-
View your repository bucket
-
Dig through the repositories to verify
-
Update
python make_s3ed.py > s3ed_sites.txt
-
python make_all_intersect_s3.py > all_intersect_s3.txt
Later, we will create a cron backup script that will run automatically.
Ongoing File Backup
-
Perform an initializing run to capture any new sites that have been added.
Then
-
python make_s3ed.py > s3ed_sites.txt
-
ls /var/www > all_sites.txt
-
python make_all_intersect_s3.py > all_intersect_s3.txt
-
sudo ./regular_git_then_s3.sh $(cat all_intersect_s3.txt)
-
this script is listed below
-
-
Verify on S3 that everything worked as planned
#!/bin/bash
#
# This script must be run as sudo.
# This script expects site names input from a file.
# Call this script thusly:
# sudo ./regular_git_then_s3.sh $(cat all_intersect_s3.txt)
# Some variables that you may choose to change.
SITEDIR="/var/www/"
REPOSDIR="/var/local/repos/"
S3BUCKET="ggis-repos"
SITES="$@"
for f in $SITES
do
cd $SITEDIR$f
git add --all
git commit -m "Regular commit of site"
cd $REPOSDIR$f
git pull
aws s3 sync $REPOSDIR$f s3://$S3BUCKET/$f --delete
done
Backup WordPress Databases
Here we perform many of the same tasks only for databases.
Assumptions
-
WordPress sites are located in /var/www. This example uses the site test.
-
Database dumps are saved to /var/local/dbdumps. The example site uses test.
-
Database names, usernames, and passwords are stored in the various site wp-config.php files.
-
Offsite backup is stored to an AWS S3 bucket. This example uses bucket-repos
Manual First Run
-
sudo -i
-
mkdir /var/local/dbdumps/
-
less /var/www/test/html/wp-config.php
-
Find the lines which define the following:
-
/** The name of the database for WordPress */ define('DB_NAME', 'dbtest'); /** MySQL database username */ define('DB_USER', 'usertest'); /** MySQL database password */ define('DB_PASSWORD', 'password');
-
Dump the database,
mysqldump --user=usertest --password=password --opt --result-file=/var/local/dbdumps/dbtest.sql dbtest
-
Compress the file,
gzip /var/local/dbdumps/dbtest.sql
-
Sync it to S3,
aws s3 sync /var/local/dbdumps s3://bucket-repos/dbdumps --delete
-
Verify with
aws s3 ls s3://bucket-repos/dbdumps/
Creating a Scripted Run
The hardest part of this script is getting the database information from wp-config.php. A python script should do the trick.
-
Find all files named _wp-config.php,
find /var/www -name wp-config.php -print
-
Use that find command piped into the python script.
sudo find /var/www -name wp-config.php | xargs sudo python mysql2s3.py
-
the script is listed below
-
#!/bin/python
"""
mysql2s3.py: Pulls credentials from the files passed via command line.
Then it calls the mysqldump command to backup databases. Finally,
it syncs the backed up databases to an AWS S3 bucket
How to call:
sudo find /var/www -name wp-config.php | xargs sudo python mysql2s3.py
"""
import sys
import re
import datetime
import subprocess
# Some variables that you may choose to change.
SITEDIR = "/var/www/"
DUMPDIR = "/var/local/dbdumps/"
S3BUCKET = "s3://bucket-repos/"
# Compile our regexes
DB_NAME = re.compile("DB_NAME.*'(.*)'")
DB_USER = re.compile("DB_USER.*'(.*)'")
DB_PASSWORD = re.compile("DB_PASSWORD.*'(.*)'")
# Build date string
todaystring = datetime.date.today().isoformat()
# Files to process passed in as command line arguments
thefiles = sys.argv[1:]
for filename in thefiles:
with open(filename) as f:
text = f.read()
f.close()
name_match = DB_NAME.findall(text)
user_match = DB_USER.findall(text)
password_match = DB_PASSWORD.findall(text)
# print(name_match, user_match, password_match)
result_file = DUMPDIR + name_match[0] + todaystring + '.sql'
arg1 = '--user=' + user_match[0]
arg2 = '--password=' + password_match[0]
arg3 = '--opt'
arg4 = '--result-file=' + result_file
subprocess.call(['mysqldump', arg1, arg2, arg3, arg4, name_match[0]])
subprocess.call(['gzip', result_file])
subprocess.call(['aws', 's3', 'sync', DUMPDIR, S3BUCKET, '--delete'])
Upgrade WordPress
Keeping up-to-date with the latest releases of WordPress and its various plugins and themes is important. WordPress is a very popular blogging platform with a history of vulnerabilities but also of quick patches. I have a tickler system that notifies me to check for updates every 3 weeks.
| Always back up your files and databases before performing a WordPress version upgrade. |
Via Admin Web Interface
Using the web interface is the easiest way for many users to upgrade their WordPress sites. It does require admin access to the site and also proper file mode settings. After each update step, verify that the site still functions as it should.
-
Login to your site as an Admin user
-
Navigate to Dashboard > Updates
-
Select which plugins to upgrade (all?)
-
Click Update
-
Return to the WordPress updates page
-
Select which themes to upgrade (all?)
-
Click Update
-
Return to the WordPress updates page
-
Under the heading An updated version of WordPress is available. click Update Now
-
Review and address any update messages that have been generated
Using WP-CLI
WP-CLI, http://wp-cli.org/, is a set of command-line tools for managing WordPress installations. You can update plugins, configure multisite installs and much more, without using a web browser.
| Follow the installation instructions at https://wp-cli.org/docs/installing/ |
| Running the sudo command with wp-cli will cause wp-cli to complain. Instead of sudo as the www-data user (which on my machines has no login privileges), I use sudo and then chown on all files back to www-data. |
Plugins
-
Return list of plugin updates available,
sudo wp plugin update --allow-root --all --dry-run --path=/var/www/tosamakers.com/html/
-
Update all plugins,
sudo wp plugin update --allow-root --all --path=/var/www/tosamakers.com/html/
-
Chown files back to www-data,
sudo chown -R www-data:www-data /var/www/tosamakers.com/html/
Themes
-
Return list of theme updates available,
sudo wp theme update --allow-root --all --dry-run --path=/var/www/tosamakers.com/html/
-
Update all themes,
sudo wp theme update --allow-root --all --path=/var/www/tosamakers.com/html/
-
Chown files back to www-data,
sudo chown -R www-data:www-data /var/www/tosamakers.com/html/
Core
-
Check for core updates,
sudo wp core check-update --allow-root --path=/var/www/tosamakers.com/html/
-
Update the core,
sudo wp core update --allow-root --path=/var/www/tosamakers.com/html/
-
Update the database,
sudo wp core update-db --allow-root --path=/var/www/tosamakers.com/html/
-
Chown files back to www-data,
sudo chown -R www-data:www-data /var/www/tosamakers.com/html/
Scripted Use of WP-CLI
WP-CLI greatly eases updating of many WordPress sites. Scripts make it even easier. First, we run a dryrun script. If you notice any problems or anything that needs special attention in the dry run, handle it manually. For those sites not requiring special attention, we then run a full update script.
Dry Run
Execute the dry run script to determine what needs to be updated and whether any special attention (via unexpected messages) should be given to a site. Call this script via sudo find /var/www -name wp-config.php | xargs sudo python update_wordpress_dryrun.py
.
#!/bin/python
"""
update_wordpress_dryrun.py: Dry runs updates on WordPress installations. The WordPress installation paths are passed via argument pipe.
How to call:
sudo find /var/www -name wp-config.php | xargs sudo python update_wordpress_dryrun.py
"""
import sys
import subprocess
thefiles = sys.argv[1:]
for filepath in thefiles:
print("----------")
print("Updates available on " + filepath[:-13])
subprocess.call('wp plugin update --allow-root --all --dry-run --path=' + filepath[:-13], shell=True)
subprocess.call('wp theme update --allow-root --all --dry-run --path=' + filepath[:-13], shell=True)
subprocess.call('wp core check-update --allow-root --path=' + filepath[:-13], shell=True)
print("----------")
Automatic Update with WP-CLI
If any sites require special attention, handle them manually; otherwise, proceed to updating the sites via script. sudo find /var/www -name wp-config.php | xargs sudo python update_wordpress.py
#!/bin/python
"""
update_wordpress: Runs updates on WordPress installations. The WordPress installation paths are passed
via argument pipe. After completion, it changes ownership back to www-data
How to call:
sudo find /var/www -name wp-config.php | xargs sudo python update_wordpress.py
"""
import sys
import subprocess
thefiles = sys.argv[1:]
for filepath in thefiles:
print("----------")
print("Updates available on " + filepath[:-13])
subprocess.call('wp plugin update --allow-root --all --path=' + filepath[:-13], shell=True)
subprocess.call('wp theme update --allow-root --all --path=' + filepath[:-13], shell=True)
subprocess.call('wp core update --allow-root --path=' + filepath[:-13], shell=True)
subprocess.call('wp core update-db --allow-root --path=' + filepath[:-13], shell=True)
subprocess.call('chown -R www-data:www-data ' + filepath[:-13], shell=True)
print("----------")
Assuming the special attention sites have already been handled manually, this should run to completion without issue.
Cron Scripts
Next up