1. 2

    Hi Chris, what is the process for adding support for new languages?

    1. 2

      To execute a code block as a script, would mainly require inserting plumping to make sure to call the right interpreter/compiler. For example, you can see an example with node.js code snippets here: https://docable.cloud/chrisparnin/examples/basics/script.md. Adding more languages, would be straightforward, but we were mainly waiting for interest in this feature before going too crazy.

      Our use cases have been mainly for building interactive runbooks we use for simple deployments and operation tasks, and supporting workshop material for our university courses, so we’ve been largely working with tools and shells.

      Finally, since the file blocks could work with any code snippet, technically, you could just make any content you want, and run the necessary command to run it, though in some cases, running a snippet directly might be a better experience.

      ```go | {type:'file', path:'sendmessage.go'}
      // Run `go get golang.org/x/sys/windows`
      package main
      import (
      var (
          user32DLL	= windows.NewLazyDLL("user32.dll")
          SendMessageTimeout	= user32DLL.NewProc("SendMessageTimeoutW")
          SendMessage	= user32DLL.NewProc("SendMessageW")
      func main() {
      	text, _ := windows.UTF16PtrFromString("Environment");
      	SendMessage.Call(0xffff, 26, 0, uintptr(unsafe.Pointer(text)) );
      ```bash | {type: 'command'}
      go run sendmessage.go
    1. 7

      Man, my least favorite Rust type is closures. They’re magical enough that they Just Do What You Want 98% of the time, and the other 2% there’s some weird borrowing issue, or the type inference gets confused, or Something Else Happens that one way or another makes them not actually interchangeable with functions.

      It’s interesting to highlight warts in Rust’s stdlib though, since a lot of work went into making it (relatively) wart-free despite doing lots of complicated stuff. Other favorites of mine: Box is slightly magical and doesn’t need to be (but did once), Path and PathBuf have never ever made me happy ever, and SocketAddr and everything related is just a mess.

      1. 2

        I seem to have avoided that 2%. What sucks about Rust’s implementation of closures?

        1. 3

          Each closure is its own type, and they are not interchangable. Plus, for a newbie, how they interact with lifetimes is a bit arcane. Coming from OCaml, this tripped me up many times when I did things like try to store a closure in a struct, have functions that returned different closures to define different behaviors, use them for partial evaluation, etc. You CAN do all of this, and the story has improved a lot with various features Rust has added over time, but it was a nasty shock.