the mapping between the empty symbol (`) and the identity function (::) is there to prevent the dict's values from collapsing into a typed array. this way i can assume the namespace's values are pointers without checking its type.
so then I have access to the symbols of a namespace, and the functions, I can then define a map of test data for each symbol in another dict who's key is also the symbol of the function, call the function on inputs defined in that dictionary
I still don't like having the names mentioned twice, that's kind of annoying
I guess with my naming schema they're already ordered
for the list, I could define arbitrary tests with (f; dayNum; optionalInput; expected) where if no optionalInput, then just read the file ../year/daynum.txt
@ngn you mean no programmatic way to populate a namespace?
@nathanrogers ns.f will try to look up that path from the root namespace. if ns is local, you should use ns[`f] instead (a problem inherited from the original k's design)
@copy many people don't. i'd better rename it to "right".
maybe. kona mentions it (in \+): "Dyadic or monadic is determined from context, default is dyadic Add : after a verb to force the monadic form, + is plus, +: is flip"
@nathanrogers i was going to suggest running each solution in isolation, like i did here (i can explain everything there), but my runner doesn't support multiple years - it should be easy to modify
@nathanrogers yes, i use one of ngn/k's extensions for forking a process and collecting its stdout: `x(("program";"arg1";"arg2");"input")
in this case the standard ."\\program" could work too (no args or input are needed)
what i don't like about ."\\program" (in both k proper and ngn/k) is that it starts a shell to run the program, instead of fork()-ing it directly. waste of pids :)
@nathanrogers you can give input when you start a process and get output when it finishes. there's no facility for getting file descriptors to a process's stdin and stdout, though i think that would be useful.
monadic < with a symbol argument is "open", it can create file descriptors for files and for client sockets. maybe "fork process and give me it's stdin and stdout" should be its job?
Ja, I really wish I had something valuable to contribute either for design or extensions or conversation, but I still feel like a foreigner in these lands
That is aside from "HOW DO I....!?"
But why not something like proc n: datatowrite for writing and reading just n: proc
@nathanrogers it's an argument to the k interpreter, e.g. k -p 1234 opens port 1234, accepts connections, reads and executes k expressions, and writes results over the socket
and it can be changed at runtime with \p 1234
it doesn't have that low-level unixy feel of dealing directly with file descriptors
What if the problem with io in array languages is trying to shove stateful behavior into arrays, and maybe it's ok to bend the design so long as the design bends the same way for operations outside your environment
the state is already managed by the operating system
all you need for reading and writing is a file descriptor, an int
for me, the statefulness of io is not a problem. the problem is to organize all the primitives for interacting with the outside world in a tidy and consistent way, ideally fitting in with the rest of the language
we've got open/close as < and >, read/write lines/bytes as 0: and 1: - those look nice and symmetrical
fork(), accept(), wait4(), kill(), .. are odd ones
with read() you need to fill a buffer and then copy it to a larger buffer, and it might need to grow.. there's a lot of copying going on, and you have to go through the whole file before being able to use it
"file" 0: 1: f does work, but here's my question, will the socket read until the end of lines, or will it read until end of what is in the socket, or some kind of socket size?
in contrast, mmap() reserves a region in virtual memory and establishes fault handlers for it, so the content there materializes only when you try to work with it, i.e. read it or write it
@nathanrogers "deallocate"? from the point of view of the process (k), it's just virtual memory, a contiguous range of addresses that you can read from and write to. it's the OS's concern to create this illusion by filling it in from disk when necessary and freeing up physical ram when necessary.
so when a message is pushed, and I'm reading from a socket, the message is already locally caching and filling up prepared storage and is just hanging out until I read from it? or it only reads complete message?
like what happens if I read from the socket while a particularly large message is mid-flight
@nathanrogers both sides in a socket have buffers for both reading and writing. tcp has mechanisms to control the flow of data, e.g. when one side is too slow, it can signal the other one to slow down too.
@nathanrogers there's no concept of a "message". if an application wants to process some sequences of bytes as a unit, it should determine their boundaries by looking at the data itself (e.g. use headers, like http does) and not rely on a particular pattern of read()-s from tcp
the tcp/ip stack is complicated. it can route your ip packets over different paths, it can split or recombine them en route, it can deliver them in a different order or not at all. tcp takes care that all that looks smooth to the user. but it doesn't guarantee that when the sender write()-s something in one chunk, the receiver will read() it in a single chunk.
so applications are on their own to determine the boundaries of "messages" that should be processed transactionally
@nathanrogers what if you're writing an online shooting game and it's more important for the bytes to arrive as soon as possible rather than only when a 0x0a byte happens to appear in the stream? one size can't fit all