dzaima / CBQN

a BQN implementation in C
GNU General Public License v3.0
329 stars 46 forks source link

Difference between Output and Returned Values #35

Closed yewscion closed 2 years ago

yewscion commented 2 years ago

Hello,

Is there a way to differentiate between values sent to stdout via a BQN program (using Show or similar) and values returned to the user at the REPL? If not, could such a functionality be added as a flag or similar?

I am most of the way through implementing Org Babel support for BQN, but my current workaround for capturing output breaks if the final command given in a block is an output that contains a newline, because CBQN will repeat the last return value at the REPL.

This is fine and makes sense, but if it could be suppressed with a special flag or marked as being a value instead of output in some way, then implementing the difference between output and value in Org Babel (and similar systems that might only care about one or the other) would be made much easier.

20220815T210345 screenshot

dzaima commented 2 years ago

There's currently no way, and adding some would be quite complicated over a single text pipe. If you want to not get REPL output, you can prepend )r to the source (i.e. )escaped ")r •Out 'a'+↕5"), but it won't help you if you want both.

Half-relatedly, making the REPL not have implicit output if the expression ends with a call to •Show or •Out has been on my to-do list for a while.

Some more programmatic REPL interface is also a thing that would be useful (including things like inspectable stacktraces, actual info about when a thing's done running, escaped messages about each output call), but is non-trivial amounts of work.

If CBQNs •ReBQN supported system value redefinition, redefining •Show & •Out to include info about their length would be an option, but alas CBQNs •ReBQN is incomplete too.

(btw, you want to escape " to \" in )escaped (and \ to \\ if you're not doing that already); it only works currently because I was lazy with my error checking)

yewscion commented 2 years ago

)r was exactly what I needed, actually. If there is no output, there's no reason to strip the value. If there is, )r will strip the return value. Sorry for the simple question; I must have missed the definition in docs/.

As for the escapes, I've implemented the ones You've mentioned, but escaping (for instance) \n as \\n prevents CBQN from interpreting that as a newline. Is this intended behavior? Should I remove the blanket escape of \ in favor of one that does not escape \n, \t, etc?

I'll need to brush up on C before I can look at the code for CBQN, but once I've finished that and learning BQN itself, maybe I can contribute to some of the goals above. Either way, thank You for this awesome project and Your quick responses to questions!

20220816T091407 screenshot

dzaima commented 2 years ago

The backslash escaping is the same as C/JS/Python/pretty much every traditional language, i.e. first you replace \ with \\, and only then replace "\" and newline → \n. So

("hello \backslash
world")

is (\"hello \\backslash\nworld\")

(and the only escapes needed are for backslashes, quotes, and newlines (both \n and \r))

yewscion commented 2 years ago

Copy that, makes sense.

I was mostly asking for the edge case of a string having a newline \n inside of it before the escapes are applied. Right now, as in my image above, such a string will have that \n escaped to \\n, and therefore the output will have a literal \n string instead of a newline. This will prevent formatting output using the \n escape string in this interface, as it will always appear literally in the output.

I suppose excluding \n and \r from the escapes would then allow the output to behave as a user might expect (expanding into a literal newline), but if that's an error maybe I can manually apply the expansion afterwards instead.

dzaima commented 2 years ago

BQN's string literals themselves don't parse backslash escapes at all. "a\nb" in BQN is a 4-character string, and interfaces should keep it as such. (there is double-quote escaping by typing it twice, i.e. "a""b" is a 3-char string, but that's unrelated)

yewscion commented 2 years ago

Copy that, will do that then. Thanks!