Key-value coding, long a staple of the Cocoa API, is accessible in Swift, with some caveats.

KVC in Swift requires NSObject

First and foremost, classes on which you intend to use KVC must descend from NSObject. It doesn’t work on base classes. So, this won’t compile:

1
2
3
4
5
6
7
8
9
10
class Boo {
var bar:Bool

init() {
bar = 0
}
}

var b:Boo = Boo()
b.setValue(true, forKey:“bar”) // this line won’t compile

but if we make Boo a subclass of NSObject, everything works as expected.

Optionals don’t work

Perhaps there’s a way of making this work; but I haven’t found it. Consider this class:

1
2
3
4
5
6
class Foo:NSObject {
var bar:Int = 0
var status:Bool = false
var name:String = “”
var boo:Int = 1
}

then we can use KVC:

1
2
f.setValue(42, forKey: “boo”)
let v:Int = f.valueForKey(“boo”) as Int

but if we change the variable boo to an optional:

1
var boo:Int? = 1

then we cannot use KVC.

I don’t listen to rap music. Since from my limited window into the lives of young adults and teens, it seems ubiquitous, I feel a need to explain why I can’t stand the genre. I don’t really even understand the difference between hip-hop and rap. I’m sure there’s a difference; but I don’t really have much of an interest in drawing fine distinctions between them.

Am I a musical snob? Nope, I’ll listen to almost anything. I have my preferences, like anyone.

So, in no particular order here are the reasons I don’t prefer rap music. Don’t tell me that you know of one or more exceptions that disproves my points. I’m not interested in edge cases because I’m making generalizations based on empirical observations. A handful of exceptions don’t change the average case.

(I’m also not interested in assertions that follow the form of “If you don’t like rap music, you’re a racist.” It’s ludicrous. How would you label an African-American person who doesn’t care for rap? Are they self-loathing because they don’t care for this particular musical form?)

Loudness

There are two problems here with rap. First, the artists seem to have a single dynamic - forte. Second, listeners follow the lead of the artists to whom they’re listening and amplify it further. The result is a loud bass-heavy thumping noise.

Of course, it’s not the artists’ fault that listeners seem compelled to over-amplify and otherwise distort their music; but it is a phenomenon that is largely restricted to listeners of this and related genres. Have you ever heard someone playing Mozart’s Ave Verum Corpus at the highest possible volumn? No. There’s something about the music or the sensibilities of typical listeners that demands listening at the dynamic intended by the composer.

Dynamic changes are one of the elements of music that endow it with nuance and interest. A musical work that has a single dynamic is uninteresting to me.

Emotion

Dynamic changes in music are closely linked to an emotion. The emotions I hear in rap music are restricted. Anger, frustration, stridency.

Historical music is filled with example of the entire range of human emotion. I worry that to the extent young people listen to rap and its related musical genres, they begin to mirror the emotions of the music that they incessantly listent to. As a result their on emotional range is restricted.

Absence of melodic value

I won’t get into a discussion about what constitutes “music”. And I wouldn’t kick the genre of rap out of the world of music. It’s has some of the typical elements of music; so I’ll agree that it’s music. But the problem with rap is that it has only a handful of musical elements - rhythm, mostly. Percussion is interesting; I can take a little solo percussion. But mostly it should be enhance an overarching musical thought. In rap, it crowds out melody. I wouldn’t argue that music must be melodius. But rap never is. Again, the restricted range of expression is rap’s most lamentable characteristic.

Lyrical content

I’m sure there a some deeper meanings that I’m missing here; but mostly I hear content about drugs, interactions with law enforcement, objectification of women, poverty, depravity, and so forth. There’s nothing uplifting or aspirational about the lyrics.

The lyrics are also based on a very restricted set of experiences that are relavent to urban culture. I’m perpetually amused by suburban kids who listen to this music and feel compelled to dress, behave, and speak in a fashion that resembles the lyrics of the music they listen to, addressing one another as “nigga”, etc. It’s an unnecessary adoption of a culture with which they are by and large unfamiliar. It seems to me that no small number of teens want to create their own versions of the distress depicted in rap lyrics so that the words are less irrelevant to them. Trying to adopt the culture extolled in these lyrics exposes young people to risks that aren’t worth taking.

The incessant use of profanity and ghetto code is gratuitous and alienating.

Egotism

So much of rap (and hip hop?) seems to be self-directed egotism. I’ve even heard artists refer to themselves in the third person in the lyrics of their own work. A piece of music should stand on its own without the need to “market” the “brand” of the artist in the song. It’s very off-putting.

Yes, I’m old; but I’m not closed-minded. I have my preferences and I’m grateful to have been exposed at an early age to the types of music that have survived the centuries because they have the nuance and beauty to capture the heart and mind.

Swift has only been out for a few weeks; but there’s a lot being written as people are playing around with the language. Here’s an annotated list of links about the language and how to get things done in it.

Introductions and basics

Style

  • Style guide - Ray Wenderlich has published his Swift style guide. I mostly agree with how he does things; but I find 2-space indentation difficult to read. It’s 4 for me.

Design Patterns in Swift

Applications of common technologies with Swift

Under the hood

NSURLSession

An example of using NSURLSession in Swift. Note, to do this in an Xcode Playground, you’ll need to import XCPlayground and call XCPSetExecutionShouldContinueIndefinitely()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import Cocoa
import XCPlayground

// allow the asynchronous task to continue, set timeout in console
XCPSetExecutionShouldContinueIndefinitely()

let url = NSURL(string:"http://97.88.225.91:5309/scheck")
var session = NSURLSession.sharedSession()

// use a separate handler function in lieu of doing it inline for clarity
func apiHandler(data:NSData!, response:NSURLResponse!, error:NSError!) {
if error {
println("API error: \(error), \(error.userInfo)")
}
var jsonError:NSError?
var json:NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &jsonError) as NSDictionary
if jsonError {
println("Error parsing json: \(jsonError)")
}
else {
let status:String? = json["msg"] as? String
println("server status: \(status)")
}
}
var task:NSURLSessionDataTask = session.dataTaskWithURL(url, completionHandler:apiHandler)
task.resume()

NSURLConnection

If we wanted to do the same thing with NSURLConnection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import Cocoa
import XCPlayground

// allow the asynchronous task to continue, set timeout in console
XCPSetExecutionShouldContinueIndefinitely()

let url = NSURL(string:"http://97.88.225.91:5309/scheck")
let urlReq = NSURLRequest(URL: url)
let queue = NSOperationQueue()

NSURLConnection.sendAsynchronousRequest(urlReq, queue: queue, completionHandler: { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
if error {
println("API error: \(error), \(error.userInfo)")
}
var jsonError:NSError?
var json:NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &jsonError) as NSDictionary
if jsonError {
println("Error parsing json: \(jsonError)")
}
else {
let status:String? = json["msg"] as? String
println("server status: \(status)")
}
})

References

In a regrettable 5:4 decision[1], the Supreme Court of the United States ruled in Burwell v. Hobby Lobby that closely held for-profit companies can be exempt from a law to which they object on religious grounds. The majority opinion delivered by Samuel Alito maintains, in essence, that the Department of Health and Human Services contraception mandate substantially burdens the free exercise of religion. Alito also wrote that the government’s penalty on Hobby Lobby would have the result that “companies would face a competitive disadvantage in retaining and attracting skilled workers.” Skilled workers? Apparently Justice Alito has never shopped at Hobby Lobby.

Justice Ginsburg wrote the dissent with Justices Sotomayor, Breyer, and Kagan concurring.

“In a decision of startling breadth, the Court holds that commercial enterprises, including corporations, along with partnerships and sole proprietorships, can opt out of any law (saving only tax laws) they judge incompatible with their sincerely held religious beliefs.”

“In the Court’s view, RFRA (Religious Freedom Restoration Act) demands accommodation of a for-profit corporation’s religious beliefs no matter the impact that accommodation may have on third parties who do not share the corporation owners’ religious faith — in these cases, thousands of women employed by Hobby Lobby and Conestoga or dependents of persons those corporations employ. Persuaded that Congress enacted RFRA to serve a far less radical purpose, and mindful of the havoc the Court’s judgment can introduce, I dissent.”

The Court is wrong.

Corporations are not people. Perhaps Texas, the Execution Capital of the US[2], would like to put one to death. Hobby Lobby is not a person. The Bill of Rights is addressed to people not corporations. Corporations don’t have religious beliefs. They make stuff, do stuff, and sell stuff. They employee people - people against whom they are not permitted to discriminate. (Or so we thought.)

Even more problematic is that the decision grants “closely-held for-profit companies” rights that ordinary individual citizens do not have. I cannot claim exemption from any law on the grounds of religious belief. But the owners of Hobby Lobby and its ilk can cry that their imaginary rights to Free Exercise are infringed; and they are granted an exemption.

To make matters substantially worse, the Supreme Court issued a temporary injunction barring the Federal government from requiring Wheaton College to fill out a form certifying that it has a sincerely held religious objection to contraception services. Such emergency injunctions are rarely granted by the Supreme Court and then only when rights are clearly infringed. In this case, it was Justice Sotomayor who wrote a scathing dissent[3]:

“Those who are bound by our decisions usually believe they can take us at our word. Not so today. After expressly relying on the availability of the religious-nonprofit accommodation to hold that the contraceptive coverage requirement violates RFRA as applied to closely held for-profit corporations, the Court now, as the dissent in Hobby Lobby feared it might, see ante, at 29–30 (GINSBURG, J., dissenting), retreats from that position. That action evinces disregard for even the newest of this Court’s precedents and undermines confidence in this institution…The Court grants Wheaton a form of relief as rare as it is extreme: an interlocutory injunction under the All Writs Act, 28 U. S. C. §1651, blocking the operation of a duly enacted law and regulations, in a case in which the courts below have not yet adjudicated the merits of the applicant’s claims and in which those courts have declined requests for similar injunctive relief.”

“The sincerity of Wheaton’s deeply held religious beliefs is beyond refute. But as a legal matter, Wheaton’s appli- cation comes nowhere near the high bar necessary to warrant an emergency injunction from this Court. For that reason, I respectfully dissent.”

“Let me be absolutely clear: I do not doubt that Wheaton genuinely believes that signing the self-certification form is contrary to its religious beliefs. But thinking one’s religious beliefs are substantially burdened – no matter how sincere or genuine that belief may be – does not make it so”

Indeed. This is precisely why the wall of separation must be high and impermeable. How can the courts test the sincerety and validity of a belief that a person or institution claims to hold as a religious belief? Since the task is impossible, it is best to afford no such exemptions. Perhaps it is best, then that each of us lives in accordance with our own values and preferences recognizing that those values and preferences are not necessarily shared by all and that we can use neither law, nor force, nor any other form of coercion to impose them on others.

These two decision undermine the wall of separation; and the authority and prudence of the Court is underminded when such capricious applications of emergency injunctive relief of a duly enacted law are granted.

What an upside-down world we live in when commercial enterprises enjoy rights that private citizens do not.


  1. Burwell, Secretary of Health and Human Services, et al. v. Hobby Lobby Stores, Inc., et al., No. 13-354 Link

  2. In fairness, Texas is not the execution capital of the US when per capita figures are considered. Oklahoma kills more of its citizens per capita than any other state. But in absolute terms, don’t mess with Texas.

  3. Wheaton College v. Sylvia Burwell, Secretary of Health and Human Services, et al. Link

While reading Juliet Schor’s book “Plenitude”, I was struck by a quote that she presents in part in the book. The quote is from Raymond Williams’ “Advertising: The Magic System”:

“It is often said that our society is too materialist, and that advertising reflects this. We are in the phase of a relatively rapid distribution of what are called ‘consumer goods’, and advertising, with its emphasis on ‘bringing the good things of life’, is taken as central for this reason. But it seems to me that in this respect our society is quite evidently not materialist enough, and that this, paradoxically is the result of a failure in social meaning, values and ideals.” [1]

Of course, when most of us refer to materialism, we are thinking about an orientation toward consumer goods, often with a obsessional focus on their symbolic values. But Williams raises a critical point, one that is key to our inaction on climate change. Although we are clearly fixated on consumer goods, we are so completely disconnected from their production that have nearly lost sight of their materiality.

The idea that we are disconnected from the means of production is in no way a new idea, of course. In the 1970’s Wendell Berry wrote that “specialization” in our societal roles was responsible for many of the problems, environmental and otherwise, that arose in the industrial era and beyond. As Michael Pollan wrote about Berry’s work:

“Our society assigns us a tiny number of roles: we’re producers (of one thing) at work, consumers of a great many other things the rest of the time, and then once a year or so we vote as citizens. Virtually all of our needs and desires we delegate to specialists of one kind or another — our meals to agribusiness, health to the doctor, education to the teacher, entertainment to the media, care for the environment to the environmentalist, political action to the politician.”[2]

When we consider the activities of humans in totality, each of us as individuals is responsible for only a tiny fraction of the knowledge and skill required to complete those activities. For example, few of us know how to fly a modern commercial jet airliner. But even those who do, have only a rudimentary idea of how the engines are put together, how the fan blades are cast, how the metal from which they are cast was mined, and so forth. The more complicated our built world becomes, the more disconnected we become from all of the details that comprise the “big picture.”

Specialization is what allows to have jet airliners and all of the other wonders of modern civilization. But Pollan and Berry point out that the unintended consequences loom large. Pollan writes:

“Specialization is what allows me to sit at a computer thinking about climate change. Yet this same division of labor obscures the lines of connection — and responsibility — linking our everyday acts to their real-world consequences, making it easy for me to overlook the coal-fired power plant that is lighting my screen, or the mountaintop in Kentucky that had to be destroyed to provide the coal to that plant, or the streams running crimson with heavy metals as a result.”

Pollan goes on to write that cheap energy is what allowed us to achieve and maintain this degree of specialization. Inexpensive fossil fuel allows us to pay others to produce our food for us and ship it long distances. As a thought experiment he asks us to consider what happens when the power goes out. Immediately we begin to think of all the things that we need to do for ourselves. We also begin to think about whether our neighbors are experiencing the same problem. In short, when energy is withdrawn from the equation of our daily lives, our connection to the community zooms into clearer focus. By artificially manipulating the cost of fossil fuel, we are making it so cheap that we can afford to hide from view the enormous costs of production.

f*ck Shell

What is the solution? Ultimately, perhaps there is no systematic solution given our planet’s overpopulation with humans. How can billions ever agree? It may be that as Wendell Berry said specialization is a “disease of modern character” and the solution lies in each of us becoming just a little less specialized and a little less dependent on consuming in a way that ignores the real costs of production.


  1. Williams, Raymond. “Advertising: The Magic System”. The Advertising and Consumer Culture Reader. Eds. McAllister, Matthew P., and Joseph Turow. New York: Routledge, 2009. 13-24.

  2. Pollan, Michael. “Why bother?”. The New York Times 2008 April, 2008. Web. 15 Jun. 2014 http://www.nytimes.com/2008/04/20/magazine/20wwln-lede-t.html Link

When executing a concurrent operation, we often use completion handlers to execute a code block on completion. In Swift, closures are the way to accomplish that task.

Declaring a function with a completion handler

In the function definition, we can fully declare the closure:

1
2
3
func doSomething(flag:Bool, completionHandler:(success:Bool) -> Void) {
completionHandler(success:true)
}

and call the function:

1
2
3
4
5
var f = Foo()
// flag parameter name is optional here
f.doSomething(false, completionHandler:{(success:Bool) -> Void in
println("value = \(success)")
})

Using typealias

In Objective-C we’d use a typedef for a block to simplify the method declaration that uses it. We can use typealias in Swift to do the same thing.

1
typealias FooCompletionHandler = (obj:AnyObject?, success:Bool?) -> Void

which can be used in a function definition:

1
2
3
func useAliasHandler(completionHandler:FooCompletionHandler) {
completionHandler(obj:nil, success:true)
}

and called in this fashion:

1
2
3
f.useAliasHandler({(obj:AnyObject?, success:Bool?) -> Void in
println("hi")
})

It appears that you still must supply the closure arguments in the function call. I could be wrong.

Here are all of my noodlings with closures:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import Foundation

// in ObjC we would define a block with typedef
// in swift it's typealias with a closure
typealias FooCompletionHandler = (obj:AnyObject?, success:Bool?) -> Void

class Foo {
// function with a completion handler
func doSomething(flag:Bool, completionHandler:(success:Bool) -> Void) {
completionHandler(success:true)
}

// function with a typealias'd completionHandler
func useAliasHandler(completionHandler:FooCompletionHandler) {
completionHandler(obj:nil, success:true)
}

/* try another return type in block */
func doSomethingElse(completionHandler:(data:String) -> Void) {
var chars:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
chars += chars.lowercaseString
var s = ""
for i:Int in 1...10 {
let r:UInt32 = arc4random() % UInt32(countElements(chars))
let index = advance(chars.startIndex, Int(r))
let char:Character = chars[index]
s = s + char
}
completionHandler(data:s)
}
}

var f = Foo()
// completionHandler parameter name is optional here
f.doSomething(false, completionHandler:{(success:Bool) -> Void in
println("value = \(success)")
})

// completionHandler parameter name may not be used here
f.doSomethingElse( {(data:String) -> Void in
println("data = \(data)")
})

References

  • Swift - Creating Methods with Closures, Michael Kral Link
  • Notes from Coding in Swift, Tal Bereznitskey Link
  • Swift Functions and Closures, Andrew Carter Link

Hailstone numbers

I was researching Collatz sequences for a tutorial I was writing on lambda expressions in Haskell when I remembered an old article from Scientific American about “hailstone numbers” that I read back in high school. Having found that article, I went looking for some of my other old favorites from the mid 80’s.

Hailstone numbers

During high school I was fasicnated by algorithms. This is a peculiar one because it involves a conjecture that hasn’t been proven. The algorithm is this: take any initial whole number value. If the number is even, divide it by 2. If it is odd, multiply it by 3 and add 1. Continue the same process until reaching 1. The sequence thus formed begins with the initial value and ends with 1. The length of this sequence is highly variable. The conjecture itself asserts that all sequences terminate with one.

The paper presented algorithms in BASIC and some version of assembly language, probably 8086. I did a lot of work in Z80 assembler back in high school and the registers don’t look familiar to me - hence my guess about 8086. The comment about BASIC being intolerably slow is funny. (You think?)

The author also talks about the possibility of using the transformations in a backwards direction as a means of gaining insight about a general proof. The problem, of course as he acknowledges, is that the algorithm is deterministic in the forward direction but ambiguous in the backwards direction.

Turning fine art into drivel

This was a fascinating and silly article that was built around Sir Arthur Eddington’s conjecture about probabilities: “If an army of monkeys were strumming on typewriters, they might write all the books in the British Museum.” The author, Brian Hayes, goes on to talk about the statistics of language and builds an algorithmic approach to generating text based on the frequency of character frequencies of n length in a source text. He goes on to experiment with combining source texts, performing mathemical transforms on the statistics, etc.

I spent hours recreating these algorithms, playing around with them, optimizing them (well as best as you could back in the 1980’s). It was all very silly; but it reinforced for me a fascination with language and free-range experimentation.

Mandelbrot

This was another article that was fascinating in the day. The utility of fractals in computer generated graphics was barely appreciated when this article first came out. In the last sentence of the paper, there’s a prescient comment about this utility: “In a future column I hope to report on some of the amazing cinematic effects produced in the Lucasfilm laboratory.” For a while, I was so fascinated by the beauty of fractals, particularly the mysterious Mandelbrot set, that bought his textbook and played around with writing a fractal graphics generator on the Mac. This was long before OS X, Objective-C, etc. I think it must have been in Pascal.

The applications of fractals are well-known now; but at the time it was cool stuff. There are still Mac-based fractal generators and explorers out there. I just checked Fraqtive which looks pretty cool.

The NY Times today ran a collection of Room for Debate pieces[1] on the topic of gifted and talented programs in public education.

One editorial[2] in particular called for the elimination of these programs on the grounds that it creates a de facto racial segregation in public education. In the New York City public school system, 70% of children are either African-American or Latino, whereas more than 70% of kindergarten students in gifted and talented programs were of white or Asian descent.

I’m about as progressive as any; but this is wrong. It is almost certainly ineffective to attempt to improve the outcomes by eliminating programs that benefit talented, motivated students. It is regretable that we (still) live in a country where such racial inequalities still exist. But stunting of opportunity is not the right way to correct it.

Those who would eliminate G&T tracks do so with the mistaken belief that if you have four children in a classroom, with IQ’s of 80,90,110, and 120; that you’ll end up with four kids of average intelligence. It doesn’t work that way. The kids on the lower end of the range may lack the foundational experiences that will enable them to take advantage of whatever benefits are mined from the G&T programs. And the kids on the upper end are likely to be bored and under-motivated by the experience. Nine pregnant women can’t deliver a baby in one month.

The recommended solution is to provide a “gifted education for all.” That certainly seems to be the egalitarian solution; but it ignores the very real difficulties of implementation. It would invariably mean more stratification of students, the very outcome the authors of this piece seek to avoid.


  1. Room for Debate (2014-06-04). The New York Times Link

  2. Potter, H. & Tipson, D. Eliminate Gifted Tracks (2014-06-04). The New York Times Link

The biggest news that Apple dropped at WWDC 2014 this year is the introduction of the Swift programming language[1].

It’s going to take a while to sort out the syntax and get used to writing in an entirely new language. I’m not quite sure what to think of the change. I’ve been thinking and writing in Objective-C for so long that it’s very comfortable. I don’t despise its square brackets message-passing notation, the way some developers who are new to the platforms do.

I’ve been learning Haskell for a few weeks and writing about it; and I’ll probably do the same for Swift as time permits. It’s hard not to just dive in, though. So hard, in fact, that I rewrote a little admin tool that I previously wrote in Objective-C. I was curious about how the interaction between Cocoa and Swift would go. The tool just scans the Downloads and Desktop directories for any “qfx” files[2] and deletes them.

Here’s the ObjC version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
@autoreleasepool {

void (^processDirectory)(NSString *,NSFileManager *) = ^(NSString *directory,NSFileManager *fm){
NSDirectoryEnumerator *enumerator = [fm enumeratorAtPath:directory];
NSString *path;
while( path = [enumerator nextObject] ) {
if( [[path pathExtension] isEqualToString:@"qfx"] ) {
NSError *deleteError = nil;
if( ![fm removeItemAtPath:[directory stringByAppendingPathComponent:path] error:&deleteError] )
NSLog(@"ERROR | unable to remove item at path %@. %@",path, deleteError);
}
}
};

NSFileManager *fm = [[NSFileManager alloc] init];
[@[@"Desktop",@"Downloads"] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString *directory = [NSHomeDirectory() stringByAppendingPathComponent:obj];
processDirectory(directory,fm);
}];

}
return 0;
}

and the Swift version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Foundation

func processDirectory(directory:String, fm:NSFileManager) {
let contents:NSArray = fm.contentsOfDirectoryAtPath(directory, error: nil)
let predicate:NSPredicate = NSPredicate(format: "pathExtension == 'qfx'")
let qfxFiles = contents.filteredArrayUsingPredicate(predicate)
for object : AnyObject in qfxFiles {
let file = object as NSString
var error: NSError?
if !fm.removeItemAtPath(directory.stringByAppendingPathComponent(file), error: &error) {
println("ERROR | while deleting file: \(error)")
}
}
}

// main
let fm : NSFileManager = NSFileManager()
let directories = ["Desktop","Downloads"]
for dir in directories {
let path : String = NSHomeDirectory().stringByAppendingPathComponent(dir)
processDirectory(path, fm)
}

  1. Apple Computer. Swift Programming Language. https://developer.apple.com/swift/ Link

  2. qfx files are Quicken files. When I download transactions from financial institutions, these are the files that get deposited everywhere. I don’t like having them sitting around; so I wrote this admin tool to weed them out periodically. It’s set to run as a cron job launch agent.