In my personal and useless opinion, this is a very broad topic that deserves to be discussed somehow. By “this”, in this particular case, I mean “drawing lines in the sand and acting like there’s a wall”.
But this is not about Prolog, or Logtalk, strictly, and it is not about assert failing, or running out of space, and I am not even sure I have an appropriate transportation metaphor ready at the moment – it would at least allow me to introduce the topic to a technical audience.
For the “us versus them”, one place to start reading, very superficially, would be “in-group and out-group”. See also the “See also” section at the bottom of the article.
For extra credit (and this concerns everyone reading this irrelevant and useless comment), compare and contrast:
How Things Should Be™, a topic close to the heart of most people; and
How Things Are at the Moment™, a topic universally hated.
I update my related blog post (https://logtalk.org/2019/11/21/handling-missing-data.html) with a discussion of the different (exception handling) semantics. Notably, using expected terms versus using catch/3 or setup_call_cleanup/3 wrappers.
The map/2 predicate takes a closure and construct a goal by appending two arguments: the stream value taken from the ExpectedStream parameter and the codes read from the stream and used as value for the expected term (ExpectedCodes) returned in the second argument. In the case that the attempt to open of the file generated an exception (e.g. non-existing file), ExpectedCodes is simply unified with ExpectedStream, thus passing along the unexpected exception.
The meta-predicate template for the predicate is map(2,*). The predicate constructs and calls the goal read_stream_to_codes(Stream, Codes). Assuming the call is successful, it unifies the variable Codes with the codes read from the stream, The map/2 predicate wraps Codes in a new expected term and unifies it with its second argument.
It is clear that map constructs and calls the goal – what is missing here – at least in my mind – from where the second argument “Codes” comes from during construction.
The Stream is bound to ExpectedStream – if open succeeded; the closure read_stream_to_codes has the Stream “appended”, which is taken from ExpectedStream – but, from where does map obtain and binds Codes as the second argument for the (read_stream_to_codes) closure – a closure that expects two arguments.