From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: Date: Thu, 20 Apr 2006 02:03:05 +0100 From: rog@vitanuova.com To: 9fans@cse.psu.edu Subject: Re: [9fans] Install from CD fails In-Reply-To: <57b9d806f3ec06df038f56c360f60867@quanstro.net> MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit Topicbox-Message-UUID: 40c95ad0-ead1-11e9-9d60-3106f5b1d025 > yes. there are a couple (okay, three) problems to address here. byron and paul haahr > addressed some of the problems with a shell called "es" years ago, even though they > didn't have dynamic modules. i had es in mind when i wrote the inferno shell (vita nuova's, not the original tiny shell). i thought then that some of the es concepts were nice, but the whole complete functional language thing was overkill and didn't get one very far (why make it possible to redefine core shell concepts such as the pipe? - it just confuses everyone if you make use of this.) inferno made it very easy to provide "internal" modules (which i called "builtins"; i never really thought of a satisfactory name) - the interface they get to see is a restricted version of the interface seen by the shell itself internally. i tried to keep this as clean as possible. (by contrast, mash, which did a similar thing, had quite a complex interface at this level). > es did this: anything passed to a function inside curly braces was passed verbatim. that was the main bit of es that i stole for the inferno shell. it works well, and combined with dynamically loaded shell modules, makes many nice things quite easy. for instance: > ; if {condition1} {body1} {condition2} {body2} is not implemented by the core inferno shell, but by an externally loaded module (std). since then, shell modules have been implemented for all kinds of things (e.g. graphics, s-expression parsing, mash-like make). externally implemented programs are still preferable (smaller interface, the shell doesn't break if the program does), for interfaces which need to maintain state across calls or wish to call back into the shell, a shell module can work well. it also makes it easy (and efficient) for a function in such a module to return a list of values (the fundamental type). the main problem is that a shell of this style has no concept of storage of any item but a string (ok, a list of strings), so it is not possible to manipulate other data items directly. also, the interface makes it quite natural to pass code fragments to external programs to execute, e.g. listen 'tcp!*!6666' {export /&} but the external programs don't have access to the original shell's environment (e.g. loaded shell modules). i don't think it's possible to address these problems without breaking the simplicity of the whole thing; the moment you introduce lexical binding, differently typed variables, etc, a whole raft of other issues starts to drift into view. another kind of language might begin to help, but that's another story. just having shell blocks as values is a big win, in my book. i don't think it would be hard to do this in rc. > a trivial grep module could make > ; grep {^fn} *.[ch] > acceptable syntax. i'm sorry, i don't see why this is preferable to the original. it has the same number of characters.