
Breaking the AGPL - phoe-krk
http://write.emacsen.net/breaking-the-agpl
======
informatimago
Let's go one step further:

(let ((p (read-from-network))) (lambda () (eval p))

ie. basically, the server program is an interpreter that loads the actual
program when it's booted.

From this, you can see that the whole discussion comes from cheating. The
actual source code, is not only the source of the interpreter, but the source
the administrator will load into the interpreter when he boots the server.
This source should also be "contaminated" by the AGPL. One may also consider
that already the GPL has the provision that you should provide all the files
required to build the program (makefiles, configurations, etc). But this could
also cover the sources of the interpreters or compilers and tools needed to
build the software, if the sources of the software depends on some specific
features from the tools. Ie. basically, any software that cannot be built from
a simple command (but requires days of work to install "dependencies",
"compilers" and "tools"), doesn't fulfill the GPL (or the AGPL)! Software
should be packaged with their gcc version (with C now evolving at such a fast
pace!) And don't give us the sources of gcc for the sources of your software,
don't cheat!

------
phoe-krk
Here's a quick writeup of why this idea is (luckily!) broken in multiple ways.

> "What's important here is that the alice function doesn't maintain state."

This merely turns variable usage into closure usage. You do not maintain state
by means of using code + variables, you maintain state by means of using a
closure-function + environment that the function is closed over. The closure-
function is compiled code; the environment is _state_.

> "Chris proposes that some programs may contain private data but at the same
> time be stateless"

This does not mean that the function is stateless; it means that state
management is pushed away from expicit variables and into the language runtime
+ GC that will collect the closure's environment when it is no longer
referenced.

    
    
        db = {
            'Alice': 'red',
            'Bob': 'blue'}
    

If you put `db = {'Alice': 'red', 'Bob': 'blue'}` in your source code, then it
is indeed source code. If names and colors come from outside, then it isn't
source code. Wrapping some user-provided data in a closure, similarly, doesn't
magically turn it into code, or even source code.

Let's imply that I have the following AGPL program:

    
    
        (let ((x (read-from-network)))
          (lambda () (sleep 60) x))
    

This is its complete source code. It reads some stuff from the network (e.g.
it makes a HTTP request), it sleeps for a minute, then it returns that data.

The thesis proposed by this post - that wrapping some data in a closure
magically turns it into not just code, but _source_ code, means that
publishing the above snippet (that is the full source code of my program, I
can run it, it will work!) is, for whatever reason, __not enough __; if I run
this program, make a network call, fetch some data from the network, and then
close the function `(lambda () (sleep 60) x)` over it, then it means that I
__must publish that data under the AGPL, since, for whatever magical reason,
it stops being data and starts being source code __.

This stupefying implication implies that closures, as a programming tool,
become __forbidden __in all programming languages under AGPL if they refer to
any kind of private data. Which is absurd.

Additionally, a closure is an instance of compiled code + environment.
Environment is state/data; compiled code, which is the part that is affected
by AGPL, is compiled from source code, which, in the above case, is `(let ((x
(read-from-network))) (lambda () (sleep 60) x))`. AGPL never applies to
_program state_ , but to source code, since no one requires you to show e.g.
the contents of all the Mastodon or Pleroma databases out there; therefore, it
doesn't apply to the environment, which is _program state_ , and only applies
to the compiled code for the closure, and requires that the source code for
that closure be published. And, by pasting the snippet of `(let ((x (read-
from-network))) (lambda () (sleep 60) x))` this requirement is satisfied.

Also, let's suppose that we have three programs that work in the identical
way:

    
    
        (let ((x (read-from-network)))
          ((lambda () (sleep 60) x)))
    
        (let ((x (read-from-network)))
          ((lambda (y) (sleep 60) y) x))
    
        ((lambda (y) (sleep 60) y) (read-from-network))
    

The first program creates a closure that is then immediately executed. The
second program and the third program invoke a function on some data fetched
from some network. The second program has a temporary variable introduced,
while the third doesn't.

Under the assumption made in this post, the first program __must publish the
value of `X` as it is source code __, while the latter two programs are fine
just as they are and don 't need to publish `X`. Which is absurd.

One more addition: instantiating a closure doesn't mean creating _any_ source
code. If I execute `(let ((x (read-from-network))) (lambda () (sleep 60) x))`,
no new source code is generated. If I execute it a hundred times, no new
source code is generated either. In all sane language implementations, all
that is generated are environment objects in memory containing user data and
the actual user-facing stuff: closure objects that bind the single instance of
compiled code to environment objects that contain data.

Yet another addition: [closures and objects are
equivalent]([https://wiki.c2.com/?ClosuresAndObjectsAreEquivalent](https://wiki.c2.com/?ClosuresAndObjectsAreEquivalent)),
as taught e.g. by SICP. Therefore, if you ever create a structure or a class
instance inside your program, you would therefore be required to publish the
values of all fields inside that object. Therefore, OOP is now forbidden if
you want to do anything that requires to _not_ publish user data.

