00:00:39 It would be nice if languages helped you write this kind of coroutine. 00:00:52 Of course you can do it yourself easily enough in a case like this. 00:01:25 async (of async/await) does something quite similar to this, but not quite the same as it doesn't handle the memory allocation 00:01:48 What do you mean? 00:02:04 (Also which language's async/await? There are many languages that assign slightly different meanings to those names.) 00:02:25 well, the general idea of what async does is that it makes a function into a state machine that can be suspended 00:02:56 although it's tied to await to choose the timing of that 00:03:14 I guess generators more generally are the general case of that 00:03:16 await is about one state machine waiting for another state machine, right? 00:03:56 -!- Sgeo_ has quit (Ping timeout: 272 seconds). 00:03:59 sort-of, it basically continues the other state machine while suspending itself, and continues itself if that state machine returns, or blocks if that state machine blocks 00:04:15 so allocating memory in this scenario is basically "await memory" 00:05:18 I think malloc is probably one of the less interesting/more extreme use cases of this sort of thing. 00:05:27 Anyway in the simple version of this allocation is just handled explicitly by the caller. 00:05:30 What would it be like? 00:05:48 no, I mean, say you need more memory 00:05:59 you do "await memory" which basically tries to allocate memory from the slice of memory you already have 00:06:11 if you don't have enough that causes a yield, with "not enough memory" as the reason 00:06:15 then the caller can resize the slice and continue from there 00:06:34 if you do have enough, then the allocation (i.e. used-length from capacity) succeeds, so you continue 00:07:16 Sure, that's an option. 00:08:52 A simple API would be something like 00:09:22 char buf[100]; SprintfState state; sprintf_init(&state, "test %d %s\n", 123, some_string); while (!state.done) { sprintf_chunk(&state); write(1, buf, state.chunk_size); } 00:10:15 not quite, you never told sprintf_init where the buffer was 00:10:25 but that's easily fixable I think 00:10:26 Oh, right, that's another argument. 00:10:39 It would either be part of sprintf_chunk or sprintf_init 00:10:42 Probably sprintf_chunk 00:11:02 Certainly sprintf_chunk 00:12:19 It'd just be sprintf_chunk(&state, buf, sizeof buf); in this case, since it never needs to refer to old memory or anything like that. 00:12:38 Hmm, this post -- https://gist.github.com/pervognsen/d57cdc165e79a21637fe5a721375afba -- and the one it links to talk about these state-machine-style APIs. 00:12:46 I was thinking of a much more radical API than this 00:13:08 yes, your API doesn't work because of this: 00:13:24 Sure, I was trying to think of the simplest case where this is useful. 00:13:24 char buf[100]; SprintfState state; sprintf_init(&state, "%s", "some really really really … really long string"); 00:13:33 string needs to go into state, but it has a fixed size 00:13:41 Why does string need to go into state? 00:13:53 Only the maximum number of varargs needs to fit in state. 00:13:55 it's the only out parameter of sprintf_init 00:14:22 or are you assuming that the caller-provided string remains allocated from sprintf_init to sprintf_chunk? 00:14:25 But state only needs to store a pointer to its arguments. 00:14:30 Yes, I'm assuming that. 00:14:45 oh, OK; that's kind-of a mentally abhorrent assumption to me 00:15:04 because it's a memory usage assumption that a) isn't documented, and b) might not be true from all calling languages 00:15:12 Really? It seems pretty reasonable to me. 00:15:19 You can enforce it with a language like Rust if you want. 00:15:34 it took me a moment to check if it was even expressible in Rust 00:15:38 I would certainly document it if I was writing documentation for this. 00:16:20 What's the more radical API you were thinking of? 00:16:30 it is, but SprintfState needs to be generic over a lifetime parameter that says how long the parameters to sprintf_init are alive for 00:16:40 -!- sparr has quit (Changing host). 00:16:40 -!- sparr has joined. 00:17:40 I think copying the erally really long string is surely more abhorrent than ensuring its lifetime is correct. 00:17:43 OK, so my idea was that you have a buffer that can be any size you like, you give that to sprintf_init and it stores as much as it can in the buffer, internal state, output characters, everything 00:18:14 if it doesn't have enough memory to do what it wants to do it stops and returns an out-of-memory, you can then realloc the buffer to be larger and rerun, it'll continue from where it left off 00:18:41 you can also dump out the characters written so far (one at a time, as many as possible, or whatever), perhaps shrinking the amount of state that's in use 00:18:47 If you think of this as a coroutine, it makes sense: A routine's arguments are presumably guaranteed to stay alive until the function returns. A coroutine's "arguments" (the arguments to _init) can reasonably be subject to the same assumption. 00:18:58 the basic idea is just that you tell it to go as far as possible, then it tells you when it stopped 00:19:08 presumably you'd have to give the same arguments with every call in this API 00:20:11 If you do that you'll presumably have to copy the string out of the internal buffer into the place you want it when you're done? 00:20:46 well, yes, but that's the same as in your example (you're copying out of buf after calling sprintf_chunk) 00:21:07 Well, I can just give it a buf that points where I want. 00:21:31 the only real difference between your and my versions is that buf and state are the same variable and state can thus steal from buf to record as much as it needs to 00:21:40 In this case it's stack-allocated but there's no reason for that in general. 00:21:58 For example if stdout is buffered I can pass my output buffer directly to sprintf_chunk. 00:22:27 hmm… perhaps this suggests some general model involving coroutines communicating with streams 00:22:28 Or if I'm writing to a C++ std::string or whatever else I can just pass a pointer to that memory. Then if I need to resize it I can pass a pointer to the new memory to keep writing. 00:22:46 it feels like fputs (i.e. the buffered version of write) is a coroutine in its own right 00:23:07 In the sense that it does a blocking write or something else? 00:23:22 in the sense that it gathers up input into an internal state buffer 00:23:37 across repeated calls 00:24:13 I guess. 00:24:23 Ugh, I always forget that fputs doesn't include a \n 00:24:34 that's why I said fputs not puts :-) 00:25:10 -!- webpack has changed nick to iczero. 00:25:46 Hmm, I should just write a sprintf with this API. 00:26:00 It's obviously much better than the regular API, which is pretty bad. 00:26:19 I should go to bed, have to go to work early tomorrow 00:26:21 night everyone 00:26:24 (There's no way to implement printf out of sprintf or vice versa, without arbitrary allocation.) 00:26:28 -!- ais523 has quit (Quit: quit). 00:26:31 Good nais523. 00:30:15 Now I wrote on a paper, a Scrabble variant, which is Go-Scrabble, which is using Go stones in addition to Scrabble. 00:34:21 ais523: I think the kind of API you're talking about is more reasonable in other cases where you have more computation going on. 00:34:51 Maybe I'd characterize it as passing an arena to your coroutine. 00:39:21 -!- Sgeo has joined. 00:41:52 -!- Sgeo_ has joined. 00:44:37 -!- Sgeo has quit (Ping timeout: 245 seconds). 00:50:10 [[Salt]] M https://esolangs.org/w/index.php?diff=65779&oldid=65776 * A * (+438) 00:54:40 `5 w 00:54:42 1/2:tall//A Tall proof is a proof with a small hole, which can only be filled by another Tall proof. \ eol//EOL stands for End Of Lawn. It's often found past the wabe. oerjan requests your presence there immediately. \ hovercraft//a-é-ro-g-liss-e-ur. If you mention eels, you'll get smacked with one of them in a most unappropriate manner. \ fisdom//Fisdom is the domination by the federal inspection station. \ operation//Operation is the opposite 00:54:46 `n 00:54:47 2/2: of cooperation. 00:55:27 `cwlprits eol 00:55:29 shachäf Zarutiän Zarutiän Zarutiän 01:00:25 [[Salt]] M https://esolangs.org/w/index.php?diff=65780&oldid=65779 * A * (+605) /* Arrays */ 01:17:55 -!- arseniiv has quit (Ping timeout: 246 seconds). 02:13:55 -!- xkapastel has quit (Quit: Connection closed for inactivity). 02:38:11 [[Salt]] M https://esolangs.org/w/index.php?diff=65781&oldid=65780 * JonoCode9374 * (+0) /* Sets */ fixed a formatting error 04:12:26 [[Truth-machine]] https://esolangs.org/w/index.php?diff=65782&oldid=65616 * Dtuser1337 * (+190) /* Madbrain */ mailbox truth machine by me. 04:38:18 `quote kmc 04:38:18 579) COCKS [...] truly cocks \ 609) You should get kmc in this channel. kmc has good quotes. `quote kmc 686) COCKS [...] truly cocks Well, in theory. \ 679) damn i should make a quasiquoter for inline FORTRAN \ 682) has there been any work towards designing programming languages specifically for stoned people \ 712) the problem with PHP is that anyone halfway competent giv 04:38:26 `quote kmc 04:38:27 579) COCKS [...] truly cocks \ 609) You should get kmc in this channel. kmc has good quotes. `quote kmc 686) COCKS [...] truly cocks Well, in theory. \ 679) damn i should make a quasiquoter for inline FORTRAN \ 682) has there been any work towards designing programming languages specifically for stoned people \ 712) the problem with PHP is that anyone halfway competent giv 04:38:31 boring 04:38:35 `quote shachaf 04:38:35 839) GreyKnight, shachaf is like a high-level Forth \ 1059) <@elliott> well, I think if you don't think figuring out who the opposite of shachaf is requires thought, then you don't know shachaf very well 04:39:10 ....what was the context for that? 04:40:04 Apparently I tried to autocomplete Factor, which as we all know begins with s. 04:45:07 hi Sgeo_ 04:45:31 Hi 04:51:06 kmc: himc 04:52:06 earlier i was going to send you a link to https://www.youtube.com/watch?v=_gKhM8gqbD8 although i don't remember why 05:00:51 lol wow 05:08:18 isn't it the cutest though 05:08:25 other than cats obviously 06:10:59 yeah 06:11:01 we saw a cat today 06:11:08 on the way back from thai food 06:11:09 standing in someone's driveway 06:11:22 did you know the government of thailand made a smartphone app that will tell you where the nearest thai restaurant is 06:11:36 they have a huge program to promote thai cuisine 06:13:52 cats are tg 06:14:15 my friend showed me a bunch of cute cat pictures he took the other day 06:14:17 it was great 06:19:18 [[Salt]] M https://esolangs.org/w/index.php?diff=65783&oldid=65781 * A * (+271) 06:23:04 [[Salt]] M https://esolangs.org/w/index.php?diff=65784&oldid=65783 * A * (+182) /* Miscellaneous */ 06:52:25 -!- pikhq_ has joined. 06:55:02 -!- pikhq has quit (Ping timeout: 252 seconds). 07:05:27 -!- AnotherTest has joined. 07:56:06 -!- tromp has quit (Remote host closed the connection). 08:03:24 -!- tromp has joined. 08:13:27 -!- tromp has quit. 08:13:45 -!- tromp has joined. 08:19:43 kmc: "void SHA1_str(Str str, U8 output[static SHA1_HASH_BYTES]);" 08:19:46 p. fancy use of static, huh 08:28:12 [[Salt]] M https://esolangs.org/w/index.php?diff=65785&oldid=65784 * A * (+77) Dumb 11-line transpiler 08:38:13 -!- Lord_of_Life has quit (Ping timeout: 246 seconds). 08:41:16 -!- Lord_of_Life has joined. 08:42:58 -!- wob_jonas has joined. 08:44:29 shachaf, ais523: re memory allocation with coroutines, this is usually done with memory alloc callbacks instead of coroutines. many libraries allow you to set a callback to allocate more memory, and some even allow you to pass a cookie to it so it can be a closure different for each state. 08:44:54 for writing to streams, a callback to do the underlying write (flush) or read (fill) from buffer is mostly already what happens: 08:45:29 [[Bitwise Trance]] https://esolangs.org/w/index.php?diff=65786&oldid=65704 * Hakerh400 * (-109) That sentence did not make much sense. In the "I/O format" paragraph it says that the program can be terminated from outside based on the output and it does not affect the computational class 08:45:40 C++ streams explicitly work that way, and C FILE effectively works that way these days, possibly with optimizations for common cases, though only glibc exposes the interface to make a FILE with custom read/write functions 08:47:04 the streams usually don't allocate extra memory, but either write to a file or a fixed-size buffer, but there are versions like asprintf that do allocate 08:48:19 mind you, in many cases you use sprintf to format a number in formats other than %f, in which case you can give a bound for the number of characters output, similarly with strftime with numeric formats, so sometimes using a fixed size buffer is reasonable 08:48:52 it's just that when you get the buffer size wrong, you get programs that mysteriously fail in months that have a long name, or some such 08:49:51 the exception is kernel interfaces, because those usually don't want to call back the user, so those are indeed implemented as coroutines that stop when they passed as much data to the process that it's allocated 08:50:29 the most common case is the read call, to which you give a buffer, and you can call it again if the kernel has more input for you 08:51:02 -!- Sgeo__ has joined. 08:51:04 Isn't the interface I specified more general and easier than an allocation callback? 08:51:10 but there's also other stuff like readlink and getsockopt where the kernel can tell you how long buffer you need, though often you can guess correctly 08:51:33 in particular, for readlink, lstat _usually_ tells you how much of a buffer you need, but that fails for /proc files 08:51:41 shachaf: usually no 08:52:12 shachaf: some functions like interpreters are complicated, and may need to allocate way deep in the call stack 08:52:20 Oh, sure. 08:52:21 so arranging to save the state and return in that case is hard 08:52:38 the kernel has to do it anyway for syscalls, like I said 08:52:54 I meant easier to use, not easier to implement. 08:52:58 and some network interfaces have to as well 08:54:23 shachaf: even that is not clear to me. with something like the lua interpreter or the gmp/mpir arbitrary precision integer functions, it's more convenient to set the allocation function once rather than to have to check the return value of almost every call and call it again if it's out of memory 08:54:40 -!- Sgeo_ has quit (Ping timeout: 272 seconds). 08:54:59 I don't think you should try to have exactly the same interface for a programming language interpreter and sprintf. 08:55:05 That's kind of silly. 08:55:17 shachaf: well sure 08:57:29 a more typical case when coroutines may help is where you're communicating through network through a protocol that requires lots of back and forth stuff, which you do often want to write as a state machine that returns each time it wants to select 08:57:33 which is how libcurl works 08:59:56 I'm also interested in how compiler support can help you make these things. 09:00:22 Anyway I wonder whether there's an implementation of sprintf specifically that behaves the way I said? 09:00:44 You can't implement either printf or sprintf in terms of the other one efficiently, which is unfortunate. 09:02:41 Hmm, does anyone use glibc obstacks? 09:02:52 shachaf: behaves as a state machine that can continue the same sprintf call? I don't think there's one, but it would be sort of unnecessary: you just do separate parts of sprintf individually anyway, and for a single one, redoing the work like you need with snprintf now is not much extra overhead to what printf already has 09:03:24 shachaf: no, but subversion uses apache's own implementation from libapr that is similar to them 09:03:27 If you have a large string output with sprintf, you need a large allocation as well. 09:03:40 Whereas printf can just use a constant-size buffer. 09:03:53 allocates everything in whatever they call the equivalent of obstacks, and then free everything at once later 09:04:02 Yes, it's probably right that you should just have your own implementation rather than relying on glibc. 09:04:12 I wrote my own and it's only a few lines anyway. 09:04:20 they can't use obstacks from glibc because glibc is rather nonportable to non-linux systems 09:04:54 I brought this up because I thought obstack had a printf function, but maybe it doesn't. 09:05:24 shachaf: either it has one, or if not, you can make one with the custom stream glibc interface, I don't recall which 09:05:37 I don't recall what APR has instead 09:05:51 let me see 09:06:42 https://www.gnu.org/software/libc/manual/html_mono/libc.html#Custom-Streams glibc C FILE streams with custom read/write callbacks; C++ streams and rust streams and python streams and perl streams have their own variants (perl has like three different mechanisms I think) 09:07:39 https://www.gnu.org/software/libc/manual/html_mono/libc.html#Dynamic-Output has obstack_printf 09:08:00 Oh, right. 09:09:32 glibc scanf has an "a" modifier that does malloc, as in "%as" or "%a[...]", which is why I think it's a mistake for C99 to have specified "%a" as equivalent to "%g" in scanf, because the glibc use is way older, 09:09:54 so in practice you can't actually use "%a" on glibc because glibc interprets it the old way, but I don't think anyone uses it anyway 09:10:09 it's just silly of C99, they are usually more careful avoiding clashes 09:10:32 it's different with clashes where neither clearly precedes the other of course, such as the two uses of "clog" 09:11:43 "remove" also clashes, but that's the same problem that the Unhinged Erase card parodies, we basically have only a few synonyms (remove, erase, delete) and a ton of functions that you try to name that way 09:12:13 One of the nice things about Xlib is that it knows three property formats: 8, which is chars, 16, which is shorts, and 32, which is longs. 09:12:34 Even if your long is 64-bit, you get an actual_format integer equal to 32. 09:17:15 I know very little about Xlib, and don't expect to have to learn more either, luckily 09:17:26 I just use higher-level libraries or programs abstracting it way deep 09:17:43 there was one case when I wanted to find out whether a certain functionality is available from Xlib, but I found a workaround instead 09:18:30 namely asking the X server to change the current virtual terminal to a different one (from the one where X lives), which X can do because it does so for keyboard shortcuts, and it's one ioctl for them anyway, but I wanted to know how to ask it to do so programmatically 09:34:34 -!- Sgeo_ has joined. 09:38:12 -!- Sgeo__ has quit (Ping timeout: 248 seconds). 09:41:32 [[Talk:Uyjhmn n]] M https://esolangs.org/w/index.php?diff=65787&oldid=61934 * Dtuser1337 * (-12) OH NOOOOOOOOOO!!! THIS MUST BE THE WORK OF AN ENEMY STAND! D: 09:45:59 [[Uyjhmn n]] https://esolangs.org/w/index.php?diff=65788&oldid=54422 * Dtuser1337 * (+66) Adding category because truttle1 forgot to add categories. 09:50:59 [[User:Dtuser1337/sandbox]] N https://esolangs.org/w/index.php?oldid=65789 * Dtuser1337 * (+106) Created page with "this is my sandbox page in which i use to draft some w.i.p stuff and experiment with these. ==some stuff==" 09:51:34 -!- Sgeo__ has joined. 09:54:45 -!- Sgeo_ has quit (Ping timeout: 258 seconds). 09:56:23 [[Talk:AAAAAAAAAAAAAA!!!!]] https://esolangs.org/w/index.php?diff=65790&oldid=14574 * YamTokTpaFa * (+249) /* I'd like to implement, but isn't it pretty difficult to implement its parse? */ new section 10:06:09 [[Salt]] M https://esolangs.org/w/index.php?diff=65791&oldid=65785 * A * (+273) /* Sets */ 10:14:05 -!- Frater_EST has joined. 10:14:51 [[Point]] M https://esolangs.org/w/index.php?diff=65792&oldid=62914 * Dtuser1337 * (-1) /* Point */ 10:16:09 [[Point]] M https://esolangs.org/w/index.php?diff=65793&oldid=65792 * Dtuser1337 * (-1) moving the infobox to the top, yare yare daze. 10:16:57 [[Esolang:Sandbox]] https://esolangs.org/w/index.php?diff=65794&oldid=65595 * Dtuser1337 * (-4137) Do i have any reason to blank this page!? 10:21:00 [[Esolang:Sandbox]] https://esolangs.org/w/index.php?diff=65795&oldid=65794 * Dtuser1337 * (+5646) testing the ASCII art. joseph joestar picture and quotes are used. 10:21:51 [[Esolang:Sandbox]] https://esolangs.org/w/index.php?diff=65796&oldid=65795 * Dtuser1337 * (+907) 10:22:18 [[Esolang:Sandbox]] M https://esolangs.org/w/index.php?diff=65797&oldid=65796 * Dtuser1337 * (-6553) blanking. Arigato, Gyro. 10:23:44 -!- ineiros has quit (*.net *.split). 10:23:45 -!- sprocklem has quit (*.net *.split). 10:23:45 -!- Hooloovo0 has quit (*.net *.split). 10:23:45 -!- Guest77811 has quit (*.net *.split). 10:23:45 -!- GeekDude has quit (*.net *.split). 10:23:45 -!- LBPHacker has quit (*.net *.split). 10:23:49 -!- HackEso has quit (*.net *.split). 10:23:49 -!- Melvar has quit (*.net *.split). 10:23:49 -!- zzo38 has quit (*.net *.split). 10:23:49 -!- lifthrasiir has quit (*.net *.split). 10:23:49 -!- jix has quit (*.net *.split). 10:23:50 -!- shachaf has quit (*.net *.split). 10:24:04 -!- LBPHacker has joined. 10:24:20 [[User:Dtuser1337/sandbox]] https://esolangs.org/w/index.php?diff=65798&oldid=65789 * Dtuser1337 * (+19) /* some stuff */ 10:24:27 -!- Melvar has joined. 10:24:48 -!- HackEso has joined. 10:25:36 -!- GeekDude has joined. 10:25:39 -!- GeekDude has changed nick to Guest24768. 10:25:45 -!- sftp has quit (Excess Flood). 10:26:06 [[Point]] https://esolangs.org/w/index.php?diff=65799&oldid=65793 * Dtuser1337 * (+18) NANI!? A year category!?!? 10:26:24 -!- sftp_ has joined. 10:27:06 -!- Hooloovo0 has joined. 10:27:15 -!- sftp_ has changed nick to sftp. 10:28:19 -!- lifthrasiir has joined. 10:28:54 -!- ineiros has joined. 10:29:22 -!- jix has joined. 10:29:23 -!- quintopia has joined. 10:29:34 -!- sprocklem has joined. 10:29:52 -!- shachaf has joined. 10:29:59 [[User:Dtuser1337/sandbox]] https://esolangs.org/w/index.php?diff=65800&oldid=65798 * Dtuser1337 * (+109) Yare yare daze 10:30:13 [[User:Dtuser1337/sandbox]] https://esolangs.org/w/index.php?diff=65801&oldid=65800 * Dtuser1337 * (+1) 10:30:46 -!- xkapastel has joined. 10:35:42 I heard that Objective C implements "blocks" with operating system support for some reason. 10:35:53 Is that true? What's the thing they need it for? 10:36:46 huh 10:38:13 are they connected to some user-space threading mechanism? 10:39:04 If not I don't really see why OS support would be needed... or helpful. But who knows what Apple's doing. 10:40:28 It could be something comparatively trivial like a hot zone. 10:42:31 . o O ( I've heard that INTERCAL implements 'come from' with OS support... ) 10:42:56 It's so easy to make up rumors. 10:43:26 It's certainly possible I misunderstood. 10:45:07 Meh the thing with these claims is that they require serious research to refute, unlikely as they seem. 10:46:22 shachaf: do you mean like by allocating executable areas or using an executable stacks to make closure stubs? 10:47:04 I don't know. 10:47:50 int-e: the intercal one is easier to believe 10:48:11 it's an esoteric language, so it may have esoteric implementation strategies 10:48:23 I was wondering whether someone would already know, not asking people to do research for me, of course. 10:49:39 I do know a few things that are surprisingly implemented with OS support: 10:50:08 one of libcoro's backend uses sigaltstack to set up stacks for newly created contexts in a somewhat portable way; 10:51:14 Windows has some neat OS support for userspace threading (though I think it doesn't go far enough). 10:51:45 It lets you transfer control to your scheduler when a thread blocks on a system call or page fault. 10:52:21 there is OS support to implement some atomic stuff, in the form of asking the OS set set some user-space flag if the OS context switches the process when some other user-space flag says that you're in some critical instruction sequence; this helps for single-processor systems on certain old processors that don't have cpu-supported atomic instructio 10:52:22 ns, 10:52:34 but these days I think they found a new modern use for it, I don't really recall what 10:57:06 shachaf: Sorry for all the negativity though. I'm mostly trying to convince myself that I shouldn't spend time going down this particular rabbit hole. 10:58:19 I thought I saw this claim repeated a bunch of times in the past but now I can't find any references to it. 10:58:54 Maybe it's the multi-core scheduling ("Dispatch") that I'm thinking of, though that seems like a different feature. 10:59:39 It's just too open-ended a question. There's a wide range of "OS support" ranging from a trivial system call (say something that fuses two other system calls that happen to occur together a lot) to special scheduler and memory system support for who-knows-what. 11:00:41 Your best bet is to find somebody who knows and I'm not that person :) 11:00:44 I know! I'm not asking you to invent or research plausible answers. 11:00:50 I wasn't even asking you at all. 11:01:09 I thought maybe typing the question in this channel would be a way to find somebody who knows. 11:01:27 Yeah, as I tried to explain, I'm susceptible to going down those trails... wasting a lot of time. 11:01:41 My fault really, not yours. You're just a fairly effective trigger. 11:02:51 (Without trying to be, I believe.) 11:02:58 Aha, I see. 11:04:43 Anyway I'm in the int-e fan club. 11:28:06 -!- cpressey has joined. 11:35:31 -!- Sgeo_ has joined. 11:37:33 shachaf: speaking of wasting time, did you ever finish any of those pillars in The Witless? 11:38:09 (I've had the misfortune of starting that game up again last weekend. But no, no completed pillar yet.) 11:39:13 -!- Sgeo__ has quit (Ping timeout: 245 seconds). 11:52:44 -!- Frater_EST has quit (Ping timeout: 244 seconds). 12:18:24 Functors adhere to a set of equational laws, so I have to imagine that they're algebraic structures in the sense of universal algebra. I also have to imagine that if I ask #haskell if they're ever studied this way, category theory will immediately come up, and won't go away. 12:19:19 cpressey: category theory may come up if you ask here as well 12:19:25 `? monad 12:19:26 Monads are just monoids in the category of endofunctors. 12:23:17 -!- ais523 has joined. 12:23:49 C-INTERCAL doesn't make use of any particular OS support, and I don't think CLC-INTERCAL does either (and am more certain that J-INTERCAL doesn't) 12:25:23 cpressey: functors are one of the building blocks of category theory; arguably the entire reason category theory was invented was to rigorously define "natural transformation" and those have functors as inputs and outputs, thus functors are kind-of a big deal in category theory 12:26:05 futexes are a good example of something that benefits from OS support, but they're only really of use in multithreaded programs 12:26:07 but what's the relationship to haskell Functors? 12:26:29 :k Functor 12:26:31 (* -> *) -> Constraint 12:26:47 I'm not sure how Haskell functors work 12:27:05 @src Functor 12:27:06 class Functor f where 12:27:06 fmap :: (a -> b) -> f a -> f b 12:27:08 @info Functor 12:27:09 Functor 12:28:42 if you pass a category-theoretic functor through curry-howard, you basically end up with a function f from types to types, that lets you map from an expression that takes type A and has a free variable list of type B, to an expressioin that takes type f(A) andd has a free variable list of type f(B) 12:28:58 the Haskell definition seems very close to that, it's just using lambdas rather than free variables 12:29:32 (the only reason the category-theoretic definition uses free variables is that there's no guarantee that function types actually exist in any given category, and in fact the input and output of a functor can belong to different categories) 12:33:14 hmm… different categories correspond to different programming languages under curry-howard 12:33:31 so that means that in theory, an fmap should be able to lift a function from one programming language into another 12:33:55 you can imagine a Haskell Functor such that f a is a Haskell type when a is, say, a Perl type 12:34:00 then fmap takes a Perl function and compiles it into the corresponding Haskell function 12:34:42 -!- ais523 has quit (Remote host closed the connection). 12:34:55 -!- ais523 has joined. 12:34:57 `? monad 12:34:59 Monads are just monoids in the category of endofunctors. 12:35:46 -!- hppavilion[1] has joined. 12:40:25 If I look at it purely algebraically, a functor is a unary operation on a monoid that preserves identity and distributes over composition. 12:42:21 So, like, ... toupper(string) is a functor? 12:43:06 toupper("H" .. "i") = toupper("H") .. toupper("i") 12:44:36 and of course, toupper("") = "" 12:45:23 [[Esolang:Community portal]] https://esolangs.org/w/index.php?diff=65802&oldid=63833 * LyricLy * (+0) 12:48:22 By the same token, monads must be algebraic structures of some kind, but their laws involve more machinery, so I thought I'd take a stab at functors first. 12:50:03 -!- hppavilion[1] has quit (Ping timeout: 245 seconds). 12:50:13 cpressey: something that confuses me when doing this, and confuses a lot of other people too, is that there are more levels of abstraction here than intuitively seems reasonable and it's easy to pick the wrong one 12:51:06 toupper isn't a functor because functors act at the type level (they operate on types, and lift functions between those types in a map-like way) 12:51:12 whereas toupper is a function that acts at the value level 12:51:24 the reason it's confusing is that all these various levels of abstraction look much the same, despite having subtle differences 12:53:02 I get annoyed doing category theory because my intuition nearly always ends up picking the wrong level of abstraction 12:53:18 There are no "types" in universal algebra, though. 12:53:38 I mean, there can be, you can introduce "sorts", but you're not required to. 12:54:03 Nothing in the algebraic definition of a functor seems to require sorts. 12:56:11 how do you declare what's a valid input to your functor, then? 12:56:15 toupper(6) isn't valid 12:57:02 If you're working with group theory, how do you declare what's a valid element of your group? 12:57:03 what? toupper(6) is totally valid, and its result is usually 6, depending on the locale 12:57:29 cpressey: this is the sort of problem that category theory is actually designed to solve 12:57:53 it takes all these "how do we define the domain of this?" problems and makes them explicit 12:58:09 so in the case of groups as seen by category theory, a group is a category with one object 12:58:15 wait... toupper acts on a string? no way, that directly contradicts to the C standard. it acts on a character. 12:58:24 wob_jonas: cpressey's toupper apparently does 12:59:13 the objects in category theory basically act as types for the arrows 12:59:19 so category theory says that in group theory, all values have the same type 12:59:22 (which makes sense) 12:59:53 ais523: I'm completely confused. I can't see how it's a "problem" to be solved. 13:00:04 anyway, functors can act on any type that exists in the language, by definition; I guess toupper on a group of strings under concatenation therefore actually is a functor, because there's only one type to map and it supports that type 13:01:58 Pick a monoid, you can define a functor on that monoid. In the toupper example, I picked a monoid of strings. Didn't give details, assumed people would understand strings, like you'd find in formal language theory and such. 13:01:59 cpressey: I guess my issue here is the "on a monoid" within "If I look at it purely algebraically, a functor is a unary operation on a monoid that preserves identity and distributes over composition." 13:02:09 functor are more general than that, you can define them even on things that aren't monoids 13:02:14 *functors 13:02:29 ``` set -e; >tmp/a.c echo $'#include\n#include\n''int main(void) { printf("toupper(8) = %d\n", toupper(8)); return 0; }'; gcc -Wall -O -o tmp/a.out tmp/a.c; tmp/a.out 13:02:30 toupper(8) = 8 13:02:48 ais523: You might be able to define them on semigroups. That seems to be hair-splitting a bit though? 13:03:04 You do need to define them on something that has a concept of composition. 13:03:08 cpressey: it's not hair-splitting at all; Functor in Haskell us /usually/ defined on things that are much more general than either monoids or semigroups 13:03:29 e.g. List is a functor in Haskell 13:03:37 ais523: A list is a monoid 13:04:03 cpressey: a specific /type/ of list is a monoid 13:04:14 but you can't do, say, [1] ++ ["a"] 13:04:36 List, the actual concept devoid of any specific/concrete element type, is a functor 13:05:36 ais523: Every kind of list you can define in Haskell is a monoid. 13:06:39 yes, but that isn't relelvant here; your definition of "a functor is a unary operation on a monoid that preserves identity and distributes over composition." doesn't apply to any specific type of list because the type of list is a monoid in its own right, not a unary operation on a monoid 13:07:36 perhaps less confusing as an example: Haskell's Maybe is a functor, but as far as I can tell it isn't a monoid and neither is a typical concrete type of Maybe such as Maybe Bool 13:08:19 ais523: How is fmap defined for Maybe? 13:08:53 cpressey: fmap f Nothing = Nothing; fmap f (Just x) = Just (f x) 13:10:28 (this operation is actually called "map" in both Java's and Rust's versions of Maybe) 13:12:23 -!- arseniiv has joined. 13:13:10 ais523: OK, I don't know what to say. I don't agree that what I'm talking about has anything to do with Haskell, but your objections seem to be based on that my statements don't make sense in the context of Haskell 13:13:35 @src Maybe Functor 13:13:35 Source not found. It can only be attributed to human error. 13:13:38 @src Functor Maybe 13:13:38 Source not found. Have you considered trying to match wits with a rutabaga? 13:13:42 @src fmap Maybe 13:13:42 Source not found. Sorry about this, I know it's a bit silly. 13:13:45 @src Maybe fmap 13:13:46 fmap _ Nothing = Nothing 13:13:46 fmap f (Just a) = Just (f a) 13:14:33 cpressey: I don't think your definition of a functor is remotely related to my definition of a functor 13:14:45 it may be an extreme special case but it's missing the general case 13:14:56 and the general case requires category theory to define 13:15:26 I'll note that Haskell's Maybe *is* a Semigroup 13:15:32 Haskell doesn't actually get all that close to the general case, but its version is more general than yours and so it makes for easy examples 13:15:51 My version doesn't have types, and this makes it *less* general somehow? 13:16:43 If my version is less general, it's because I went with monoid instead of semigroup. I'm happy to backpedal on that. 13:16:47 cpressey: yes, because you're requiring everything that your functors apply to everything that exists in the universe of discussion, which is a major restriction 13:17:46 the existence of types makes things more general because it allows functors to specify how they behave when multiple different types are in use 13:17:59 "Types are useful when you have types" 13:19:04 I don't know, are you assuming I'm talking about programming? I'm not. 13:19:18 um 13:19:30 no, I'm using programming terminology though because I assumed that category-theoretic terminology wouldn't be understood 13:19:50 to the extent that things other than programming are interesting, types are useful outside of programming too 13:22:23 hmm… if we restrict ourself to one category and one object, we end up with a semigroup (as you say), and then the category-theoretical definition of "functor" collapses to "function on semigroup elements that preserves identity and preserves composition", which is your definition 13:22:27 without types, you end up trying to less-than compare a set of points to a 3xn matrix of complex numbers, or water your 13:22:35 or microwave a kitten, 13:22:54 and you won't notice that you shouldn't do those things until you get a runtime exception such as the cat dying 13:23:04 wob_jonas: I don't think microwaving a kitten is a type error, it's a bad idea for other reasons though 13:23:21 hmm 13:24:14 cpressey: let me see if I can explain why functors are more general than the semigroup definition: suppose you have two /different/, unrelated, semigroups; but it's possible to define a map from one to the other which preserves identity and preserves composition 13:24:33 that's still a functor 13:24:55 (there are two generalisations from your definition to the full category-theoretical definition; Haskell generalises it in one dimension, the above example is the generalisation along the other dimensioin) 13:25:01 can you give a more concrete example for that? 13:25:25 wob_jonas: the simplest example is the degenerate map which maps everything from the first semigroup to the identity element of the second semigroup 13:26:05 ok but... that doesn't really answer cpressey's question 13:26:49 wob_jonas: I'm trying to answer the question "My version doesn't have types, and this makes it *less* general somehow?", by explaining one way in which the category-theoretical definition is more general than cpressey's is 13:27:22 you can think of more useful examples, e.g. there's a functor from the integers-plus-addition to the (integers mod 7)-plus-addition 13:27:25 that simply takes the value mod 7 13:27:40 preserves identity, preserves composition, it's useful to have a name for this sort of operation 13:27:56 isn't that called a monomorphism? 13:27:59 no 13:28:02 a homomorphism 13:28:07 make it a homomorphism 13:28:15 but I thought functor was something other than that 13:29:00 wob_jonas: well, yes, a functor is more general 13:29:07 or, hmm 13:29:12 I don't mean more general 13:29:14 a homomorphism /between semigroups/ is a type of functor 13:29:18 this isn't true for things other than semigroups, though 13:29:23 I thought homomorphisms just weren't functors 13:29:44 but I don't think I understand what a functor is 13:30:32 let's see… in a category, you have objects and arrows (with each object having an identity arrow, and arrows composing) 13:31:01 for example, in the category representing a semigroup, there's only one object, its identity arrow is the semigroup's identity, and more generally arrows are elements 13:31:44 ais523: I am still at a loss why your "more general" definition of functor, rejects that toupper() is a functor, while my "less general" defintion accepts that toupper() is a functor, as well as accepting all of your examples are functors as well. 13:31:57 but aren't the categories with arrows between supposed to be a generalization of algebraic structures with homomorphisms between? 13:32:11 a functor is a map between categories from objects to objects and arrows to arrows that preserves identity and composition 13:32:12 what is a "category representing a semigroup" then? 13:33:01 cpressey: it turns out that it doesn't reject that toupper is a functor, as long as your source and target categories are very limited (specifically they both have to be the semigroup category of strings under concatenation) 13:33:11 wob_jonas: a category with one object is equivalent to a semigroup 13:33:36 cpressey: I just hadn't realised you were considering such a limited universeof objects 13:33:39 ais523: Yeah, *I'm not thinking in category theory terms*. 13:34:04 hmm 13:34:30 so there's one object, plus an arrow for each element of the semigroup, and the arrows compose by the semigroup operation? 13:34:38 wob_jonas: right 13:35:00 so that's like the object with the internal morphisms 13:35:05 that makes sense 13:35:22 hmm no 13:35:23 not quite 13:35:40 but ok 13:35:48 cpressey: in this case I guess you have a valid definition of a special case of a functor (specifically, the case when you're only considering a single semigroup); and if you were working in other settings, the same more general definition could be used to provide a special-case definition for those settings too 13:36:25 ais523: I think that is more or less how abstract algebra works? The thing I said about group theory, remember. 13:36:55 There is usually no assumption that there are multiple kinds of objects you have to distinguish 13:37:15 Algebraic structures, with their associated homomorphisms, form mathematical categories. Category theory is a formalism that allows a unified way for expressing properties and constructions that are similar for various structures. 13:37:38 And therefore we *must* analyze them with the tools of category theory 13:37:43 No thanks. 13:38:02 it's more, category theory is the tool that mathematicians use to specify how the various algebraic structures of abstract algebra relate to each other 13:39:39 It is *the* paradigm, can't escape it, huh. 13:39:47 my experience with category theory is that it's more or less impossible to do anything in abstract algebra that doesn't have a category-theoretical interpretation, and that is typically the most general possible interpretation; whether you actually want to think on that level or not is up to you, and it often isn't useful to do so 13:40:04 it's mostly only useful when you use it to take a proof from one area of mathematics and use it to prove a theorem in another 13:41:33 I hope I didn't give the impression that that was what I was aiming to do, because it wasn't. 13:43:44 -!- Frater_EST has joined. 13:44:06 well, I thought you were interested in learning about what functors were in general 13:45:20 "Functors adhere to a set of equational laws, so I have to imagine that they're algebraic structures in the sense of universal algebra. I also have to imagine that if I ask #haskell if they're ever studied this way, category theory will immediately come up, and won't go away." 13:45:39 in particular, I had no way of knowing that you were thinking of the definition as specialised to semigroups as the specific definition you were concentrating on, as opposed to merely being an example of the general definition 13:45:54 [[MUSYS]] https://esolangs.org/w/index.php?diff=65803&oldid=65330 * Salpynx * (+189) Some new examples for an old language. I've started working on a simulator. 13:46:01 I'm not sure how you got "in general" from "in universal algebra". 13:46:33 Or even what "in general" means, in this context, to you. 13:47:00 I didn't realise you were considering a special case; "functor", to me, refers only to the general case 13:47:15 there's nothing in your statement that suggests that you have a specific special case of functors in mind 13:47:29 This is rather frustrating. 13:47:38 and the mention of #haskell increased the chance that you were thinking of a definition that's at least as general as Haskell's 13:48:19 fmap id = id; fmap (f . g) = (fmap f) . (fmap g) 13:49:24 I pointed out toupper() conforms to these laws; you said it's not a functor; then later you admitted, okay, it can be a functor. 13:49:40 there are /three/ Functor laws in Haskell 13:50:18 Better update https://wiki.haskell.org/Functor then 13:50:19 it doesn't comply with the third, which is fmap :: forall a b. (a -> b) -> f a -> f b 13:51:14 it's just that Haskell enforces that one by the compiler rather than making the user check that it applies manually, so it doesn't have to be written in a comment 13:52:18 now, the reason toupper is a functor on the semigroup of strings, even though it isn't a functor in Haskell, is that the semigroup of strings only has one type – strings – and we have f String = String and forall a b. a = String && b = String 13:52:55 but in Haskell, "f" has to be a type constructor and there's no type constructor f for which f String = String, also it's not true that forall a. a = String because Haskell has other types 13:53:43 Haskell has types. It sure does. 13:54:09 It has kinds, too! 13:55:05 I'm tempted to go correct that wiki page anyway; Haskell's Functor is not a general representation of mathematical functors, it is specialised to the case in which the type-level mapping is a type-level constructor (rather than a type-level function that isn't a type constructor) 13:56:32 (it's also specialised to categories whose objects are Haskell types, but given that it's being imlpemented in Haskell, that's forgivable) 14:04:27 cpressey: sorry if I annoyed you by the way; I'm really tired at the moment and that makes it harder for me to predict how my actions will affect other people emotionally 14:07:21 -!- Sgeo_ has quit (Read error: Connection reset by peer). 14:08:27 -!- Sgeo has joined. 14:32:44 -!- Frater_EST has left. 14:34:04 ais523: but isn't that limitation solved in a ghc extension, as in type families? 14:34:24 -!- wob_jonas has quit (Remote host closed the connection). 14:54:06 -!- ais523 has quit (Quit: quit). 15:15:32 [[User:YamTokTpaFa]] https://esolangs.org/w/index.php?diff=65804&oldid=65163 * YamTokTpaFa * (+106) 15:16:30 [[ArrowFuck]] https://esolangs.org/w/index.php?diff=65805&oldid=62003 * YamTokTpaFa * (+60) +CATs 15:31:01 -!- cpressey has quit (Quit: WeeChat 1.4). 15:44:18 [[Special:Log/newusers]] create * Ntrupin * New user account 15:45:44 -!- zzo38 has joined. 15:55:04 [[Special:Log/newusers]] create * EdgyNerd * New user account 16:01:00 -!- b_jonas has joined. 16:21:04 -!- tromp has quit (Remote host closed the connection). 16:22:53 -!- tromp has joined. 16:26:25 -!- Phantom_Hoover has joined. 17:08:46 -!- FreeFull has joined. 17:14:17 -!- tromp has quit (Remote host closed the connection). 17:25:06 -!- tromp has joined. 17:31:43 -!- palaiologos has joined. 17:34:20 -!- palaiologos has quit (Remote host closed the connection). 17:34:35 -!- kspalaiologos has joined. 17:41:05 -!- kspalaiologos has quit (Remote host closed the connection). 17:56:38 -!- tromp has quit (Remote host closed the connection). 18:25:44 -!- tromp has joined. 18:42:26 -!- tromp has quit (Remote host closed the connection). 18:42:50 -!- tromp has joined. 18:51:27 -!- choochter has joined. 18:57:49 -!- choochter has quit (Quit: Leaving). 19:00:42 int-e: I haven't played that game in a long time. 19:00:52 I don't think I completed any pillars? I don't remember. 19:13:32 -!- tromp has quit (Remote host closed the connection). 19:39:48 -!- MDude has quit (Ping timeout: 244 seconds). 19:48:26 -!- tromp has joined. 19:52:31 Wow, long conversation about functors. 19:52:44 It looks like mostly people talking past each other? 19:53:05 -!- tromp has quit (Ping timeout: 250 seconds). 19:55:21 A monoid homomorphism is clearly a special case of a functor, and so is Haskell's Functor class. 19:55:41 What's all the argumentationing about? 20:02:23 Maybe *is* a functor, but it's a functor "on" Haskell functions, in the usage above. 20:02:53 The reason the "on a monoid" isn't general enough is that Haskell functions aren't a monoid because you have different types so you can't compose any arbitrary functions. 20:03:59 Whereas «[1] ++ ["a"]» is a red herring because that's not the functor operation that's being discussed ([Int] and [String] are both monoids, separately, and there are no type issues there). 20:04:13 I don't know whether cpressey logreads. 20:13:33 * kmc is back from surgery and feeling good. 20:16:05 -!- tromp has joined. 20:18:09 higan mchelloister 20:18:20 -!- tromp_ has joined. 20:19:17 hi 20:19:54 hichaf ben-kikello 20:20:37 -!- tromp has quit (Ping timeout: 252 seconds). 20:22:49 -!- tromp_ has quit (Ping timeout: 252 seconds). 20:37:23 -!- Lord_of_Life_ has joined. 20:39:40 -!- tromp has joined. 20:40:03 -!- Lord_of_Life has quit (Ping timeout: 245 seconds). 20:40:16 -!- Lord_of_Life_ has changed nick to Lord_of_Life. 21:32:12 kmc: congrats on surgery 21:33:31 ty 21:37:37 -!- AnotherTest has quit (Ping timeout: 252 seconds). 21:39:15 -!- xkapastel has quit (Quit: Connection closed for inactivity). 21:50:21 kmc is now a surgically-enhanced superhuman 21:51:46 something like that 21:52:52 do you do double damage now 21:52:53 https://www.supermegacomics.com/index.php?i=333 22:01:11 hmm glowing blue and quad damage 22:35:03 -!- FreeFull has quit. 23:45:46 -!- arseniiv has quit (Ping timeout: 246 seconds).