On the critique of PORT!

From chat

Well you know Rebol PORT! was crap

There's obviously a wider context for this statement with that discussion, however there's something I'm not clear of in your (@hostilefork's) port! critique:

  • for sure the TCP scheme is flawed—you've found plenty of work in evaluating HTTPD alone

  • It's likely the file scheme will have similar glaring flaws if the tires are kicked sufficiently

  • I don't know too much about the serial port scheme/extension (is it even a scheme?)

  • stdin, stdout and stderror were dropped for implementation expediency in the move from Rebol 2 (though there was no stderror therein)

  • We have a few other higher-level schemes with various degrees of love and care

Does your overall 'crap' verdict extend to the PORT! datatype concept and structure itself (language quirks pertaining to naming—per aforementioned event names—notwithstanding)?

I've built a few schemes for Rebol 2 and 3 over time and I do tend to like the concept of these malleable interfaces with their tight association with the core verbs and the url!/file! types (it's possible I'm biased given my own investment in that way of thinking).

I do believe scheme authoring could benefit from much more transparency and documentation—there's still a degree of mystery as to the specific mechanics (particularly when building schemes on top of the TCP scheme). In general though I see ports/schemes as being in that small set of Rebol's core and compelling distinguishing features.

My confusion may just come down to the terminology used (ports/schemes/specific schemes), but I'm open to the prospect that my own perspective is misguided and that perhaps ports are an attempt at oversimplification of complex systems.

*that small set being something like: data representation, evaluation model, parse/dialecting, size/self-containment (Tiny Elvis) and ports/schemes. Would also add 'embedability' based on your own efforts in honing the API and the Amish constraint on the source.

From a terminology perspective, it would definitely be helpful if Rebol stuck to common names when things are common. It's unfortunate that Red is perpetuating calling Generic Functions ACTION!s.

Does your overall 'crap' verdict extend to the PORT! datatype concept and structure itself

In the moment, I was just speaking out of annoyance with the implementation. Failure handling was nearly non-existent, and authoring of correct code even impossible if you assume no failures. (I'd argue that the absence of a READ/PART in the TCP scheme is indicative of a kind of fundamental misunderstanding of how sockets work...but at least I have added that feature.)

The very broad idea of using generics is fine and likely appropriate: to be able to say write port data instead of what most languages would get with file.write(data) or socket.write(data), it's all right. When you're going for English-like syntax and trying to get the number of typed characters (and visualized glyphs) down, it seems like a sort of lower-limit.

But when you have refinements (e.g. /PART or /LINES on READ), where then only the file port implements it and it just gets dropped otherwise...it's very frustrating to look at it and have to ask:

  • "How many of these refinements are there in the long tail? If more get added, will every existing PORT! be responsible for it?"
  • "If code lives in the generic READ to handle something like READ/LINES regardless of port type, how can it be abstractly implemented to build the result block one string at a time vs. read the entire binary data at once?"
  • "What does it mean when we can't take for granted the result of READ or WRITE will be bytes...e.g. in the progressive scenario of building a block above?"

It's very difficult to see how READ and WRITE can serve so many masters. So this seems to me to require at least some level of separation of a byte-stream transport layer which you can stack up, and then some other articulation for codecs (including streaming ones).

The READ/WRITE level in my view might be ideally a much more accessible way of doing C++ iostreams, with "insertion" and "extraction" operators. If you look at Boost.ASIO it does the same sort of thing as Rebol TLS, where you chain together a TLS stream on top of a TCP stream.

As for how you get from there to encoding or decoding Rebol structure, well maybe that's what codec design is for. And maybe you can attach codecs to ports (perhaps disabling READ and WRITE at the byte level so you don't muck it up, and only let you use LOAD and SAVE?)

There may be great potential for designs here, but someone has to do it. I was hoping it wouldn't be me. :-/

1 Like