Can I give my object a resource I have already opened?

← Error Handling and Exceptions · Ref: Q1840

Not if something else already owns it. Every closeable value has exactly ONE owner, and that owner closes it. A closeable property (closed by its type's operator close) and a try-with-resources resource (closed when the try ends) are slots that will close what they hold, so a closeable may enter one only when it is NEW - a constructor call such as Journal("audit"), or a call whose declaration returns a new closeable, such as TextFile(path).input() or a function that returns a Journal it made. Anything else is error E81062: a parameter (the caller owns it), a try resource, your own property or another object's property already has an owner, and storing it again would close it twice - and close it while its first owner is still using it.

A constructor that stores its own parameter in a closeable property takes ownership of it - a transfer - so every construction must hand that parameter a new value. Logger(Journal("audit")) is right: the logger is the journal's only owner. Logger(journal), with journal a try resource, gives one journal two owners, the try and the logger, and is E81062 at the argument. The same holds when a constructor forwards its parameter to super(...), and a parameter may go into only one property.

Code that only USES a resource someone else owns takes it as a parameter and leaves the closing to its owner - the loan pattern. The program below gives the logger a new journal and lends a second journal to a function; every close prints, so you can see each journal closed exactly once.

Example

defines module qa.errorhandling.closeableslotneedsanewvalue

  defines class

    Journal
      name as String?

      default private Journal()

      Journal()
        -> label as String
        name: label

      write()
        -> text as String
        stdout <- Stdout()
        stdout.println(`${name}: ${text}`)

      operator close as pure
        stdout <- Stdout()
        stdout.println(`closed ${name}`)

      default operator ?

    <?- Keeps the journal it is given: a transfer, so it must be handed a NEW journal -?>
    Logger
      journal as Journal?

      default private Logger()

      Logger()
        -> target as Journal
        journal: target

      log()
        -> text as String
        journal.write(text)

      default operator close

      default operator ?

  defines function

    <?- Only uses a journal someone else owns: a parameter is a loan -?>
    note()
      -> journal as Journal
      journal.write("borrowed")

  defines program

    FreshStoreDemo()

      try
        -> logger <- Logger(Journal("audit"))
        logger.log("started")

      try
        -> journal <- Journal("notes")
        note(journal)

Common mistakes

E81062 — Logger keeps the journal it is given in a closeable property, so it must be handed a NEW one. A named try resource already has an owner, the try, and both would close it. See ek9 -h E81062 for details.

Incorrect:

        ->
          audit <- Journal("audit")
          logger <- Logger(audit)

Correct:

        -> logger <- Logger(Journal("audit"))
Other ways to ask this
  • Why is 'logger <- Logger(journal)' an error when journal is a try resource?
  • Why can't I write 'try -> mine <- param' to make sure a parameter is closed?
  • Can a try resource be another object's property?
  • What does E81062 mean?

Coming from another language?

Java: 'new BufferedWriter(writer)' takes the writer, and closing both the wrapper and the original in two try-with-resources blocks closes it twice; nothing stops you. C#: 'leaveOpen' flags and CA2000/CA2213 analyzers try to track who disposes what. Rust: moving a value into a struct transfers ownership, and using the moved value again is a compile error. EK9: a closeable may enter a property or a try resource only when it is new (E81062), so every closeable has one owner by construction.

Keywords: loan, close, constructor, transfer, operator close, try-with-resources, E81062, ownership, fresh, new value, closeable, property