Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Do you have more to share, like resources about capability-safe languages, or your ongoing work?

> This also means that object capabilities aren't "colored" like async/await, monads, or other effect systems.

That's interesting. How does that work? Is it by passing around a value from your main function to the functions that need it?



> Do you have more to share, like resources about capability-safe languages, or your ongoing work?

I can share an example from the main function of the self hosting Firefly compiler [1]:

    main(system: System): Unit {
        ...
        let fs = system.files()
        if(fs.exists(tempPath)) { deleteDirectory(fs, tempPath) }
        ...
    }

    deleteDirectory(fs: FileSystem, outputFile: String): Unit {
        fs.list(outputFile).each { file =>
            if(fs.isDirectory(file)) {
                deleteDirectory(fs, file)
            } else {
                fs.delete(file)
            }
        }
        fs.delete(outputFile)
    }
Main is passed `System`, which is a value with methods to access the network, the file system, etc. It passes on the `FileSystem` value to `deleteDirectory`, which only has methods to access the file system.

Since there's no other way for `deleteDirectory` to obtain capabilities than to recieve them as arguments, `deleteDirectory` only has access to the file system.

> That's interesting. How does that work? Is it by passing around a value from your main function to the functions that need it?

Exactly; such arguments can themselves be seen as "coloring", since they show up in the function signature. However, an important distinction is that you can capture capabilities in the fields of an object or in closures, and thus get rid of the coloring.

The Firefly language is quite far along - nearly feature complete, and translating itself. However, there's a lot of work left before it becomes a viable alternative to existing languages, not least in the tooling and documentation department.

[1] https://github.com/Ahnfelt/firefly-boot/tree/master/compiler


Thank you for the example, that helps a lot. So for example, when you write a library that need capabilities, you would write it using dependency (capability?) injection, and then the main program would have to pass an object with that capability for the code to work? And I see what you mean by "they are just plain values, and require nothing special from the type system", as long as you restrict what part of the program can produce a System or a FileSystem, you can just use plain typechecking.


Yes, dependency injection (without DI frameworks) is pretty much what it is! Just taken a bit further to the logical conclusion.

I would point to an online resource, but honestly I haven't run across any that does justice to the simplicity of the concept.


I'd say our conversation right here is a good example. Most people understand static typing, most people understand DI. Once you have those, the only part left to understand is the concept of capabilities. If you have all of those, your example is clear and simple. Maybe adding a type annotation to show that fs is a FileSystem in main, but that's about it.

I think you've done a good job of minimizing what's required for the average developer to go from not knowing about capabilities to using them.


Great! Maybe I can ask for your feedback once we've produced some documentation?


Yes, I would be very interested. My email address is in my profile.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: