00:00:00 --- log: started retro/12.09.30 01:18:32 docl : thanks! i'm still arguing with that guy in my head, months later :) 06:56:44 :) 08:38:49 --- join: kumul (~kumul@adsl-72-50-90-224.prtc.net) joined #retro 08:43:41 revision 364 has the new words: functions and also shows function names in 'explore' 08:43:48 sweet 09:39:38 --- quit: clog (^C) 09:39:38 --- log: stopped retro/12.09.30 09:40:07 --- log: started retro/12.09.30 09:40:07 --- join: clog (~nef@bespin.org) joined #retro 09:40:07 --- topic: 'Retro Language | http://retroforth.org | Logged @ http://rx-core.org/dev/rancid | Latest Release @ http://s3.retroforth.org/download/11.x/retro-11.4.tar.gz' 09:40:07 --- topic: set by crc on [Tue Jul 17 13:54:58 2012] 09:40:07 --- names: list (clog kumul tangentstorm @ChanServ SimonRC karswell_ ivan`` docl yiyus oPless saper @crc) 10:11:56 --- join: erider (~chatzilla@unaffiliated/erider) joined #retro 10:14:56 hi erider 11:07:18 tangentstorm: that guy seemed to miss your point. but he was kind of right that you were abusing the word "concurrent" to include paging stuff that is actually sequential 11:08:06 tangentstorm: on the other hand the point you were going for was that OO is compatible with concurrency, i.e. works just fine in concurrent environments almost by definition 11:08:56 at least if you do it right. I'm still a little confused about how modern languages pseudo-OO works against that. 11:11:19 rereading 11:15:05 hey all 11:15:44 hi tangentstorm 11:16:38 docl: i guess the point i was trying to make is that objects are inherently concurrent... like conceptually, they're separate machines that share no state whatsoever, communicating only through message passing 11:17:51 systems like erlang or unix qualify as objects to me because they treat programs that way 11:18:12 the fact that they may be implemented under the hood by one master process switching back and forth is just an implementation detail\ 11:18:28 conceptually concurrent yeah, but you want to avoid seeming to say that automagically makes them work on real hardware 11:18:39 well it does 11:18:52 but the objects everybody is used to don't work that way 11:18:58 no locks and threads? 11:19:22 or is the locking and stuff basically happening in a hidden way 11:19:35 * docl has the barest grasp on this 11:19:51 you don't really need locking because there's no shared state :) 11:20:28 hmm. trying to picture how that works. 11:20:36 you and i are communicating via messages right now... we could collaborate on a project, and we wouldn't need locking 11:21:02 take an sql database for example. you get 2 write messages. one has to happen before the other. 11:21:42 even file locking in older version control systems is kind of a byproduct of using giant text files 11:22:11 * docl always kinda suspected locking is a case of doing it wrong. 11:23:15 well, okay... there probably are all kinds of places where you do need some kind of locking mechanism, but i don't know what they are :) 11:24:14 what i was saying about languages like java not really doing OO the way it was intended has to do with the fact that instead of message passing, you use function calls 11:25:09 interesting. what distinguishes the two? 11:25:17 the way most languages work today, methods are just functions / subroutines in some other namespace, and the caller blocks until the subroutine finishes and returns the result 11:25:37 should methods be something more generic? like a quote maybe? 11:26:03 in erlang, you just send messages and get messages. there is never any waiting for the result from another node. 11:26:43 ... were you the one talking about monads the other day? I have no idea how to scroll back in my irc client :) 11:26:52 yeah that was me 11:27:13 yeah.. well i was saying the compiler state was a bit like a monad in forth. 11:27:21 also was babbling about yield and generators, which I have the barest grasp of as well. 11:27:22 but i forgot about retro's class handlers 11:27:53 class handlers... i don't think that's the rigth word... lemme find the docs 11:27:59 yeah class handlers kind of get in there and change the word around in terms of what it does 11:28:11 like .word .macro .data 11:28:22 yeah that's what i mean 11:28:37 i'm thinking that's where you'd implement monads in retro 11:28:43 .word executes it, unless compiler state is true then it compiles it 11:29:29 .data shoves it on the stack, unless compiling in which case it compiles with a "literal" machine code 11:29:55 a monad's basically just a function that expects a certain kind of package, does something with the data inside, and then puts the result back in the exact same kind of package. 11:30:15 forth itself is a monad that uses a stack as the packaging type 11:30:39 takes a message, supplies a message 11:31:21 so imagine that you have a process that you want to do over and over again... like raytracing all the pixels in a 3d scene.... or some kind of big map-reducy program like a google search 11:32:31 you could have a big loop through all the pixels, but you could also just have one computer per pixel 11:32:59 cause it's not dependent on the output of the others? 11:33:09 let's say that in order to render one pixel, you have to do steps a, b, c, and d. 11:33:56 in java you do : pixel render( x, y : int ) { a(); b(); c(); d(); return this.pixel } or something. 11:34:28 err... return this.rgb probably, since pixel is a type there :) 11:34:34 that kinda code just does not make sense to me 11:35:23 in forth you would write: : render ( xy-c ) ( c meaning "color" ) a b c d ; 11:35:42 right 11:35:55 but there's a huge huge difference here 11:36:14 and a, b, c, and d would all be like ( xy-xy ) except d would be (xy-c) maybe 11:36:21 yes 11:36:31 or you'd initialize a variable and have them each use the same variable 11:36:38 in a real monad, they'd all be xy-xy 11:36:55 well okay let's call it the RAY monad 11:37:00 they'd all be of type ray 11:38:29 so : render ( rxy-rc ) ( points and colors in the ray monad ) a b c d ; 11:39:10 maybe you stick the r on top, and shuffle it to the return stack and back each time... 11:39:35 so a b c and d are all handled by the .ray class? 11:39:37 anyway "ray" is the box and it contains all the info about the scene that you're rendering... or at least the parts needed for the raycasting pipeline 11:40:17 hrm 11:40:25 how about this 11:41:24 --- quit: kumul (Quit: WeeChat 0.3.8) 11:41:27 so : render ( xyr-cr ) ( points and colors in the ray monad ) (( a b c d )) ; 11:41:36 where (( and )) are like the "do" block in haskell 11:41:52 they'd be immediate words that change the behavior of the compiler 11:42:21 and i guess since retro doesn't have a type system you'd have to also tell it about the ray monad 11:42:22 ok 11:42:26 okay.. let me back up then :) 11:42:54 you could probably use [[ a b c d ]] in that case I think, as long as they are defined right beforehand. 11:43:40 the basic idea about monads is that you're separating the box-handling from the handling of what's in the boxes 11:44:17 so if you stick something into tho UPS monad you can move it around the country, no matter what it actually is 11:44:23 those switch the compiler off and on without compiling in an exit. or you could accomplish the same thing by making the words type .macro 11:44:25 the whole world basically 11:45:00 well what they'd need to do is inside of there, you need an extra parameter that says which box-handler you're using 11:45:07 UPS, Fedex, snailmail, etc. 11:45:38 in this case, it would be a container called "ray" 11:45:48 ok 11:46:46 okay, so... this isn't the world's greatest metaphor, but... the forth data stack is the box, and the forth address stack is the label 11:46:49 "ray" is a function at this point? a block of code? 11:47:28 i'm not sure. 11:47:41 block of memory to be written to? 11:47:47 could be both 11:47:49 it's just a marker that says what monad you're in 11:47:55 ok 11:48:20 see... like.... lemme show you a question i aksed on stackoverflow, because the guy that answered it kind of blew my mind about monads 11:48:43 http://stackoverflow.com/questions/7024248/monads-at-the-prompt 11:49:27 it's the one at the bottom with 10 upvotes that i was thinking of 11:51:05 honestly, i don't understand exactly what he's saying even now, but the gist of it is that "do" and ">>>" and "return" ... they work with IO, Maybe, [], State ... pretty much anything 11:52:16 well.. my metaphor sucks because a monad really is both the different kinds of package and a different "postal worker" for each kind of package 11:52:55 hmm. so when you say these a b c d funcs are in the ray monad, what does that imply? 11:53:07 if you execute do { a; b; c; d; return rgb } in haskell, the type would be... 11:53:41 :: (Monad m)=> m a -> m b 11:53:43 pretty sure. 11:53:51 not 100% sure, but i think that's right. 11:54:22 it's like a tag? 11:54:57 return takes a value and packs it back into whatever monad you're talking about 11:55:12 "return to box" 11:55:27 do { } is syntactic sugar for the real thing, which is something like this : ( it's been a while ) 11:56:36 a >>= \x b x >>= \y c y >>= \z dz >> \rgb rewrap rgb 11:57:06 where x, y, and z are values of some arbitrary type we don't need to know about 11:57:22 but in retroforth, their types would match the stack comments for a, b, c, and d 11:57:51 so the (( )) would be macros that do this transformation 11:58:06 ( \x b x ) is lambda x : b(x) in python, btw 11:59:22 and >>= is "put the result in a box, ship it to the next thing in the chain" ... where the next thing is a lambda that takes a box with something in it 12:00:46 the trick is that each monad has its own version of " >>= " 12:01:16 or at least its own verson of "wrap" and "unwrap", which >>= uses 12:01:20 no 12:01:36 >>= unwraps return wraps sorry :) 12:02:28 okay. so how about this: the monad is both a special size / color of box, and special handling instructions for putting things into, taking things out of, and transporting those kinds of boxes. 12:03:19 so do {{ }} is like the guy in the mail room, that knows whether to send a particular box through ups, fedex, local courier, etc. 12:03:52 do { } in haskell and my (( )) concept here 12:04:59 but: in retroforth, there already is one and only one kind of box, and it always contains two stacks and a dictionary 12:06:30 maybe "image" is the better word... it's really the mutable variables that are important, and i'm not sure if they're really in "the dictionary" 12:07:25 anyway... so all that means is that everything is already running inside the "Retro" monad 12:09:20 but monads can take parameters... which means they can be nested... like, the list monad can contain submonads, like this:: [ Maybe [ Either ( Maybe int ) ( String )]] 12:10:17 each do { } only cares about the topmost, outer layer ... so in this case do { } would be in the list monad, which is basically foreach() 12:11:22 hmm. we have code that steps through a list. like "words" 12:12:12 and if you wrote a retro interpreter in haskell, you'd write a Retro monad that would basically be a retro interpreter. 12:12:47 should I be thinking "monad = separate sub-program"? 12:13:00 like you would say do { push; no_op; inc; divmod } .... and all of those things would be functions of type Retro a -> Retro b 12:13:30 monad is a stupid word :) 12:13:35 :) 12:13:43 it doesn't correspond to any one thing in the physical world 12:14:03 except 'burrito' :) 12:14:21 it's a tag, like you said, along with instructions to pack, unpack, and transport. 12:14:57 so for [] ( the list monad ) ... the packing operator is called cons, the unpacking operator is called head or car, and the "transport" is called foreach 12:14:59 'tag with associated behaviors that are consistent with the types of things we are doing stuff with' 12:15:33 yeah 12:15:42 or you could think of it as an object with 3 methods 12:15:59 or rather... it's an interface that consists of 3 methods, which any object can implement 12:16:12 pack, unpack, transport? 12:16:16 yes 12:16:51 let's call it handle 12:17:02 hrm 12:17:04 yeah 12:17:30 pack, unpack, handle?? 12:17:46 because there may be special instructions not just for UPS, but for everyone that touches the box in the assembly line, etc... 12:17:50 yes 12:17:54 ok 12:17:57 that makes sense 12:18:15 list is super basic, I can generalize from that 12:18:19 but not like "if your name is fred then do this.." 12:18:32 they're universal handling instructions like 12:18:39 "this thing is radioactive" 12:18:51 which is basically what the IO monad is 12:19:02 :) 12:19:11 user danger 12:19:26 "this code is potentially unsafe.. so if you don't have a hazmat suit, you mustn't touch it" 12:20:47 IO is special because... you as a programmer are "inside" the IO monad and thus have no way to access "unpack" 12:21:09 which is what prevents you from passing IO values into purely functional code 12:21:21 okay... so that's monads 12:22:41 now... here's the thing... since forth words already have the single container type.... we have some flexibility 12:23:06 we could chose to use one retro interpreter that executes a, b, c, d in sequence 12:23:52 hmmmm. like a saved copy of retroImage? 12:25:34 or we could have one retro interpreter each running a loop that looked like this: : main ( - ) begin readstate a dumpstate repeat ; 12:25:53 and others that did the same for b , c and d 12:26:07 and then chain those together with unix pipes 12:26:10 or telnet 12:26:16 or carrier pigeons 12:26:59 :) 12:27:04 that's message passing ... 12:27:59 now that i think about it, dumpstate probably doesn't even need the return stack.. and the only variables that need to be in there are the scene data for the pixel we're rendering 12:28:04 currently reading your blog post btw 12:28:28 yeah.. it's like 22 pages.. i tend to ramble a bit :D 12:28:31 yeah, you would want to restrict to relevant data 12:28:39 the state I mean :P 12:28:50 well, yeah.. but also... you don't really need to return 12:29:07 if i send you a message, you can reply or not 12:29:13 true 12:29:49 if we're in an assembly line, i can pass you the thing i'm working on, and you don't need to come back after each one and tell me it's done 12:29:58 i'm not your boss, i'm just the guy next to you in the chain 12:30:13 but in java, i'm your boss 12:30:47 and once i pass the widget to you, you do your thing, and pass it to the next guy... and then it has to get passed back the chain to me, and then i pass it to the guy on the other side of me 12:30:57 and then he does the next step and passes it down some other chain 12:31:05 yeah. I hate that mentality in programming. like the crazy programs in windows that demand full admin privileges. 12:31:25 because in java, you're not really passing a message, you're invoking a function. 12:31:32 :) 12:32:29 so in java's version of OO, there's only one widget being worked on at a time in the entire factory... unless we use threads adn then sometimes you wind up with 2 widgets at once or whatever 12:33:07 woah that's crazy 12:33:11 in a real object oriented system, there's one widget active for each person 12:33:28 and ideally you find the slowest guy and everybody moves at his pace 12:33:57 so that's the difference between real object oriented programming and what java does 12:34:41 we should totally aim to replace java :) 12:34:42 what i was going to say about monads is that because retroforth has the return stack and it has the "class word" concept... 12:35:14 you could have a thing that said "OKAY! THE POINTY HAIRED BOSS IS COMING! EVERYBODY KICK IT JAVA STYLE!" 12:35:53 then later: "whew, he's gone!... let's do it the other way" 12:36:32 :) 12:36:40 i'm being unfair to java though 12:37:08 say step b is slow 12:37:17 you can hire 10 b guys 12:37:57 ... well... 12:38:01 hrm 12:39:26 okay... some idiot in department B left the door open and everyone in the factory died of radiation poisoning from the IO monad 12:39:30 you're the only one left 12:39:48 guess what? you put on your hazmat suit, and you follow the java rules, because there's only one of you. 12:40:23 so the widget flows through the same stations ... but because you're carrying it back and forth 12:40:41 those rules make perfect sense when there's only one worker in the factory. 12:41:32 and that pointy haired boss started this whole place on his own and that's how he did it and became a millionaire, so obviously that's how it ought to be done now, right? 12:42:37 no.. as an entrepreneur, he had an inherrently concurrent process, but he treated it as a sequential one because of a resource constraint. 12:45:13 so basically java is a smart entreprenuer that struck it rich in the widget business which later got bogged down in bureaucracy because he couldn't let go of the past, and would have failed long ago if there weren't so many smart guys on the line compensating for him. 12:45:18 the end. 12:46:21 lol 12:47:44 no.. i skipped over the point i was trying to make :) 12:48:21 SOME processes are inherently concurrent but are implemented sequentially due to a resource constraint like having only one thread of execution. 12:49:02 but there are other processes that are inherently sequential... like, say, generating the mandelbrot set 12:49:38 we can dedicate one worker or team to each pixel on the display 12:50:47 that's inherently concurrent, because the mandelbrot set is just the set of all coordinates ( imaginary numbers ) that have a particular boolean property. 12:51:17 so if you have an infinite number of computers, you can test the entire set of imaginary numbers at once 12:51:29 right 12:51:39 or generating bitcoin hashes 12:51:40 but : the test itself is iterative... 12:51:44 yes 12:51:59 same thing with bitcoin.. you have to do the hash function, and it takes time 12:52:10 and you can't just take all the steps and do them at once 12:52:15 because they depend on each other 12:52:32 you may be the world's best adder, but if i say what's two plus... 12:52:39 you have no idea until i finish the sentence. 12:52:57 so that's inherently sequential 12:53:39 and for that there's no point hiring one guy for each step... you do it the way old man java did... one guy doing one step at a time 12:53:59 so... 12:54:21 you don't REALLY want to just yell out "everybody switch from sequential to parallel processing" 12:54:50 you want to say "you guys over here can be in parallel" ... "you guys over here need to use the return stack" 12:55:28 but always remember that one guy alone can do the work of any parallel team. 12:55:54 so.. if you make a "parallel" class in retroforth... 12:56:09 it can choose at runtime to distribute the work to other retroforths, or do it all in one node 12:56:22 based on available resources 12:56:29 with bitcoin mining, the goal is to generate lots of hashes as quickly as possible. so they use parallel processing for that a lot. 12:57:58 yeah :) i've never really done any bitcoin mining, but i've studied the problem because it's a good test case for this stuff. (and also i was hoping to get rich!) 12:58:05 but obviously each of those processes has a certain indivisible complexity that has to be done sequentially 12:59:00 yes... the hash function has a lot of "waiting for the results from the other guy" 12:59:10 gtg 12:59:24 I'll be back later to read the logs :) 13:00:53 haha.. i think i'm done... :) the point was just that you can use the "parallel" class as a monad... and then update the class handlers to account for which monad is active 13:01:31 13:01:38 later 13:50:29 --- join: arescorpio (~arescorpi@222-206-17-190.fibertel.com.ar) joined #retro 16:21:45 tangentstorm: maybe I could visualize it better if I had a working example in front of me. 16:22:09 hi a 16:24:34 hi erider 16:24:40 good evening 16:25:07 * crc is starting to think about exporting parable code into C or Python 16:25:32 * docl is still reading http://b4lang.blogspot.com/2012/09/sprawl-or-oberon-forth-and-stackwise.html by tangentstorm. 16:25:51 I remember ZZT and Commander Keen :) 16:25:56 hi guys 16:27:13 Commander Keen was the first computer game I played... 16:27:42 does it work on freedos, I wonder? 16:27:43 commander keen's probably all grown up now and still wearing that helmet. 16:28:03 I was disappointed he never saved the universe. 16:28:29 Apparently he got shot in a secret level of Doom or some such. 16:28:39 well... we're still here so maybe he did... maybe he just did. 16:28:42 docl: it should. it works under dosbox (I've used that to run it on os x and windows machines) 16:34:26 docl: there was a part of doom where you could kill keen: http://images.wikia.com/doom/images/d/dc/Map32_commander_keen.png 16:36:33 aww :( 17:05:33 --- join: kumul (~kumul@adsl-72-50-90-224.prtc.net) joined #retro 17:31:39 i've been thinking about the bootstrapping process some more. the way the metacompiler works now, there's a dependency where you have to have an image to get an image 17:33:43 but it's possible that the words are arranged such that if you have the tools for building the dictionary entries ( the meta compiler, i guess )... then you could do the whole thing from ngaro assembly language 17:36:15 there's a point where the system becomes self sufficient and each newly defined word can only be defined in terms of previous words. 17:37:05 originally the initial kernel was written in assembler using an assembler written in toka (which erider is fond of) 17:37:09 but i'm confused about whether that point is the first entry or if there is a little bit at the start where the earliest words are defined in terms of later words. 17:37:28 :) 17:38:54 if there's a tangle up front, i'd like to untangle it. once there isn't a tangle, i want to rewrite the metacompiler in machine code. 17:39:27 or just write an implementation in machine code.. i wouldn't necessarily advocate that you actually use the code :) 17:41:28 the problem is that I assumed that a full retro would be used to build a new one, so I used a lot of the later features 17:41:56 yeah 17:41:58 (parable avoids this, mostly, since the parser is part of the vm, and only [ ] and define are needed to build the rest) 17:42:37 this is something that needs to be dealt with for retro12 (someday...) 17:43:07 but... when you say you use the later features... do you use them in the metacompiler itself, or in the definitions? 17:44:26 i think i ought to be able to answer this myself by looking at the meta.rx file but i get confused not knowing the class of each word 17:44:27 both. I know that prefixes are used in the definitions (for handling the initial strings for the dictionary and such) 17:45:10 yeah but prefixes execute at compile time, right? 17:45:35 they're just macros that expand to something else in the actual definition that gets written to the image... (?) 17:45:42 prefixes are essentially a class handler, they execute interactively or at compile time 17:46:32 e.g., __" is used for building strings. if compiling, it'll embed the string, compiling a jump and such around it, or if interpreting, leaving it in the rotating string buffer 17:46:46 IIRC, this is the only prefix needed by the kernel at this point 17:47:45 meta-alt.rx has the start of a metacompiler code using only the kernel-provided functions 17:48:18 the test for whether it's tangled or not is this: does there exist a word anywhere in the dictionary such that the *compiled* definition has an implicit call instruction referring to a word with an address later on in memory. 17:49:02 argh.... gotta go. bbl. :/ 17:49:10 ttyl 18:04:54 https://gist.github.com/3808899 18:14:46 cleaned up a bit 18:15:23 doesn't save the stack or anything, but does save where at in the function you were when you hit the yield. 18:15:54 not sure if it's useful or not though. 18:25:18 works with : foo ( - ) 10 repeat dup putn yield 1- 0; again ; 18:32:51 docl: interesting 18:33:40 i'll take a closer look at this tomorrow 18:33:49 :) 18:35:09 hmm. the stack diagram is now confusing because it leaves the counter on the stack until it hits 0. 18:37:54 on the other hand, conceptually, it hasn't stopped running until then. 18:39:00 true 18:42:11 that might be a use for a class handler, to track the stack before it starts so yield can compile in code to grab anything from the stack when it exits / add it back in when it resumes. 18:43:03 do we have a way to save the stack state / restore it? 18:44:33 alternately we could just change the stack diagram to reflect what it might do, ( - || -n ) 18:45:19 at this point there is no way to save/restore stacks 18:48:06 I could probably come up with something, but it would be wasteful in terms of space and cycles 18:49:53 yeah 18:56:58 otoh : foo ( n-n ) repeat dup putn yield 1+ again ; is valid 18:58:16 that may be more the expected format for a generator anyway 20:39:00 --- quit: arescorpio (Quit: Leaving.) 21:51:34 --- quit: kumul (Quit: WeeChat 0.3.8) 23:59:59 --- log: ended retro/12.09.30