There Came an ECHO

I just fixed a bug in Sea of Words...which hopefully means it's a little more trustworthy.

It seemed like a good time to add the ECHO feature I've talked about.

>> echo It's this feature, which I've described in the past.
It's this feature, which I've described in the past.

ECHO is a variadic function which processes what you pass it to the end of line. If you prefer, you can also use a BLOCK!.

>> echo [A block allows
    you to put an arbitrary number
    of newlines]
A block allows you to put an arbitrary number of newlines

>> echo [Or two echos] echo [on the same line]
Or two echos
on the same line

There is a variable substitution mechanism so you can use @ to point out variables or expressions.

>> x: 10
>> echo The value is @x
The value is 10

>> echo The doubled value is @(x * 2)
The doubled value is 20

It's Shorter!

Can't argue against that.

print ["You have written" num-lines "lines of code."]

echo [You have written @num-lines lines of code.]

echo You have written @num-lines of code.

The API Benefits

Not needing quotes helps API calls:

rebElide("print [{You have written}", num_lines, "{lines of code.}]");

rebElide("echo [You have written", num_lines, "lines of code.]");

rebElide("echo You have written", num_lines, "lines of code.");

It's the kind of change that opens up the choose-your-own-adventure of syntax to let you build a system more like bash, or less like bash. It's an important decoupling of the use of words from the creation of variables. So, onward.


Only downside is for use in oneliners that will need a newline after what is to be echoed. For every other use it looks perfectly fine!

How does ECHO work when debugging is complete and the line is added at the start:

echo: :none ; disable debugging print lines


echo It's this feature, which I've described in the past.  ; should now have no effects or side-effects

Hello, @Cplus. Welcome... and please do feel free to introduce your background and interests on the Introductions Category...

How does ECHO work when debugging is complete and the line is added at the start:

echo: :none ; disable debugging print lines

You can't really replace a function with NONE in the general case in order to make it a no-op, and if it evaluated its arguments you can't make that a no-op in the general case. (Weird attempts to calculate how much to skip over run afoul of cases where the evaluations being skipped would affect the arity of subsequent things you're skipping.)

So if you wish to leave a callsite untouched but change the definition, you need something that will mirror the interface of the thing you're replacing. That will always involve some attention to what the old parameters were. But it's a good point that variadic interfaces are harder to clone.

For a function like ECHO, one avenue of attack could be to say that ECHO is actually a specialization of something like ECHO* which takes a destination to write to:

echo: specialize :echo* [where: system.ports.stdout]

So then, when you get in this situation where you want to "redirect to /dev/null" you'd have some way of saying that:

echo: specialize :echo [where: #]

The reason I chose # there is due to precedent for "opting in" to things but throwing them out:

>> var: #

>> set var 10
== 10  ; doesn't error, but doesn't actually set anything

Being a representation of ASCII's NUL (0) it's a bit of a pun on "/dev/null":

>> append #{ABCD} #
== #{ABCD00}

But there are other reasons why it makes a good choice for this purpose...specifically in how it relates to multiple return values.

Maybe that's all interesting--or maybe it makes you sorry you asked. Hopefully the former. :slight_smile:

1 Like

Ah well, With Print, commenting out one of the two lines below acts to turn debug printing on or off:

pfd: :print ; print for debug on
pfd: :none  ; print for debug off

In use:

pfd "routine entered"
pfd ["counter is" c-count]

Echo would appear harder to incorporate in a debugging repertoire.

If what you pass to PFD is not a literal block or text, but an expression that calculates a block or text...that expression will be evaluated. It might just be wasteful calculation that gets discarded, or maybe it has side effects. Maybe you want those side effects when debugging is enabled or perhaps not, but it's dicey.

If inline debug printing interest you, the development of invisibles and -- for dumping might be worth looking at. The idea is years old now and could use some updating, but completely vanishing expressions are still very versatile:

Ah well, no matter.

It is perhaps an inevitable consequence of the increase in complexity from rebol-2 that simple debugging techniques are no longer viable.

In thinking about the variable arity well as string interpolation...I started wondering if maybe giving ECHO a string should imply interpolation.

Look at this line from the HTTP server stress test:

print [{CLIENT} n {: Will read} partial {/} total {bytes}]

This isn't really even the spacing that I wanted. Getting that would be laborious:

print [
   {CLIENT} unspaced [n {:}]
   {Will read} unspaced [partial {/} total] {bytes}

I've made this a little better with GET-BLOCK!s reducing and the resulting BLOCK! implying unspacedness:

print [
   {CLIENT} :[n {:}] {Will read} :[partial {/} total] {bytes}

That's cool when you're building code up programmatically, but this is a statically templated string. Being forced to be messier than that sucks.

But With Interpolation...

echo {CLIENT $n: Will read $partial/$total bytes}

I kind of like the idea of defaulting to saying that if you don't use delimiters like $(...) then it assumes you're using a simple WORD!, and it wouldn't try to read any further than that. So it would see dots or slashes as terminal--as above. But you could put things like field selections or function calls in a group, like $(now/hour) for example.

Anyway, the concept here would be that if you give ECHO a string it would act like PRINT INTERPOLATE of whatever that string was. And then, if you give it a BLOCK! it would have the literalness that helps API clients splice values directly.

What's a bit annoying here is that being able to actually have $XXX access environment variables is extremely handy in scripting. So maybe we could say @XXX are language variables and $XXX are environment variables? :-/ I don't know.

1 Like