Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lang: Discussion about 'worlds' for handling fs side-effects #249

Open
i4ki opened this issue Nov 16, 2017 · 0 comments
Open

lang: Discussion about 'worlds' for handling fs side-effects #249

i4ki opened this issue Nov 16, 2017 · 0 comments

Comments

@i4ki
Copy link
Collaborator

i4ki commented Nov 16, 2017

Today I read this paper about Worlds, a design/construct to control the scope of side effects in programming languages.

The solution is brilliant and solves several hard to solve problems very nicely. The basic idea is add a primitive called world to the programming language (much more interesting if first-class) to isolate changes in scopes. All computations happens inside a world, and new worlds could be 'sprouted' (word of the author) from existing ones inheriting their state, but changes in the 'child worlds' doesn't persist in the parent until commited. The idea is similar to transactions (as in STM), but much more powerful as it could be used to solve problems not related to parallel computations also.

I really recommend the paper, but talking about nash, I think it gives insights on a good design to control other kinds of side effects that really hurt in a shell, like filesystem changes.
Use cases I'm thinking about (The examples expects objects to exist in the language, for clarity sake).

  1. Rollback filesystem changes in cases of errors;
in $world.sprout() {
    var _, status <= cat /tmp/other-file > existent-file.cfg  # this file will be truncated if cat fails
    if $status == "0" {
        # propagates the fs change to parent (global fs) only if commands succeeds.
        $world.commitfs(); # '$world' here refers to child world
    } else {
        # handles here what to do in case of error
        # but fs doesn't need to be rollback manually
    }
}
  1. Create temporary workspaces/environments
var tmpWorld = $world.sprout()
var nfiles = ""
in $tmpWorld {
    mkdir /tmp/test
    process-files -output /tmp/test
    nfiles, status <= ls /tmp/test | wc -l
    if $status == "0" {
        # here we only commit the variables (the $nfiles)
        # As fs isn't commited, nothing is propagated to global fs
        $tmpWorld.commit()
    }
}

3- Filesystem layering (persistent or in-memory)
4- Undo broken OS updates

in $world.sprout() {
    apt-get update
    # nash will abort in case of error, then not committing to parent fs
    apt-get upgrade 
    $world.commitFS()
}

5- Builtin concurrency mechanism alternative to synchronization locks (related to #247)

But as we're in the path of a non-sharing concurrency mechanism, I don't think this could be useful.

Maybe there're other use cases that I'm not aware for now.

Talking about implementation, the 'worlds' to control side-effects of variables is pretty easy to implement, but what would really benefit us (i think) is the fs effects, but on linux this will require namespaces (mount ns at least) and in-memory (or optionally persistant filesystems for huge changes) layered filesystems and will require some unionfs (overlayfs, aufs, etc) on the system.
It's "doable" (I think) but don't know if worth the effort mostly because then nash will depend on a lot of OS features...
But my feelings say that this could push innovative ways of shipping software and/or create software tooling. Maybe something to keep in mind =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant