cancel
Showing results for 
Search instead for 
Did you mean: 

kdb+ paster

cillianreilly
New Contributor III

Here is a utility function I wrote to allow multi-line pasting into the kdb+ console. I find this very helpful when debugging or stepping through code, as I can copy in chunks of code, rather than line by line. I keep it in my q.q file.

I'd seen this idea once or twice, but I never really liked those implementations. Most used a while loop (or worse, the while keyword) or prompted for some string input to terminate. This version uses convergence on the input string and the number of lambdas in the input. (i.e. it won't converge if you've opened a function and not closed it - this handles the edge case of blank lines inside functions). Entering a blank line, with no currently open lambdas, terminates the program.

paste:{
        value                                           // evaluate gathered input
        ({
                $[(""~r:read0 0)and not x;              // read input, check current function count
                        (x;"");                         // return initial state, halt convergence
                        (x+/124-7h$"{}"inter r;         // increment/decrement function count
                        y,` sv enlist r)                // append latest input, host line separator
                        ]
                }.)/                                    // apply to 2 item initial state and converge
                [(0;"")]                                // initial state
        }

Some interesting bits:

1. read0 0 prompts for input and reads from STDIN
2. x+/124-7h$"{}"inter r; increments or decrements the function count. The ASCII values for "{" and "}" were remarkably convenient for tracking. This allows for blank lines inside functions, without terminating convergence.

q)124-7h$"{}"
1 -1

3. ` sv enlist r; When the left argument is a null symbol, and the right argument is a list of strings, joins the strings on the host line separator. This appends a newline to the input - deals with comments in the code.

q)` sv enlist "//comment"
"//comment\n"

Here's an example.

q)paste[]
test:{
    x:x*4;
    // comment
    x-2
    }

q)test
{
    x:x*4;
    // comment
    x-2
    }
q)test til 10
-2 2 6 10 14 18 22 26 30 34

For those without comments or blank lines in their code, the very succinct forms below can be used instead.

{value{x,read0 0}/[""]}
k){.{x,0::0}/[""]}

This does not work inside a context with \d. If you want to define something in a namespace, use the full context name in the input.

3 REPLIES 3

davidcrossey
Moderator Moderator
Moderator

Thanks for sharing @cillianreilly!

David

SJT
Contributor III
Contributor III

So useful a tool should be hauled out of the flow and kept handy.

Should Cillian preserve this post as (say) a GitHub Gist and list it in Awesome Q? Somewhere else?

cillianreilly
New Contributor III

Always room for improvement. There is no need to pass the number of open lambdas between each iteration when that can be easily checked during each iteration. Now there is no need to pass a 2 item list, we can just converge on the input string itself. The true condition in the above version is also a bit suspect, this is cleaner.

paste:{value{$[(""~r:read0 0)and not sum 124-7h$x inter"{}";x;x,` sv enlist r]}/[""]}

@SJT, happy to write this up for Awesome Q.