IRC channel logs

2014-11-25.log

back to list of logs

<BW^->davexunit,civodul,*: so is there any POSIX thread support to start with?
<BW^->POSIX thread support.. yes?
<BW^->so Guile does POSIX threads *only* and does *not* do any green threads atop of that, right?
<dsmith-work>BW^-: Right, unless you implement them yourself using delimited continuations.
<dsmith-work>BW^-: So says the civodul
<BW^->mhm
<BW^->dsmith-work: wait, there's call/cc right
<BW^->?
<BW^->dsmith-work: or what do you mean by delimited here, why mention it at all?
<ft>BW^-: Delimited continuations are documented under "Prompts" in the manual.
<ft>API Ref. → Control Mechanisms → Prompts
<BW^->ok
<BW^->ft: the point here is just to get call/cc but at a lower CPU expense, right?
<turbofail>no, the point is to get a more useful control flow than what call/cc would normally give you
<turbofail>the cpu expense isn't all that different
<BW^->hm
<BW^->turbofail: what different in semantics here?
<BW^->turbofail: i never really understood what delimited continuations do or are of value for -
<BW^->turbofail: as I got it, their point was to put less stress on CPU or heap than call/cc
<BW^->the stack trace needed for creating the instance would be more superficial, and the stack frames it binds would be limited (unlike the unlimited for call/cc)
<BW^->something like this
<turbofail>the simplest illustration of the difference is doing something like (define c (call/cc (lambda (k) k))). if you look at c now, you'll see a continuation object. but then if you call (c 5), and then look at c again, you'll see that c is now 5
<turbofail>whereas if you did (define c (reset (shift k k))) and did (c 5), it will return 5, and then when you evaluate c again you'll still have that continuation there
<turbofail>because the continuation no longer includes the define
<turbofail>this ends up being a lot more useful, because the fact that call/cc captures the entire rest of the program is really inconvenient. you end up stomping on parts of the program you didn't intend to
<turbofail>the more important part of it is not just the fact that it only captures part of the control stack, but also that it lets you transplant that portion of the control stack wherever you want, whereas call/cc is kind of "rooted"
<BW^->hm
<BW^->turbofail: can you clarify your last point, re transplant vs rooted?
<turbofail>you can kind of fake a delimited continuation by combining call/cc with a bunch of set! statements, but it's not a good way to do it, and i don't think it's possible to get it entirely right
<BW^->turbofail: okay, (begin (define c (call/cc (lambda (k) k))) (define d (print "Hello world\\n")))
<BW^->so (c 5) prints Hello world again - okay.
<BW^->turbofail: again I don't understand your last point :)
<BW^->set! ?
<BW^->transplant? root? what :))
<turbofail>when you call the continuation c, it ends up re-executing everything that happened after you captured the continuation, redefining c in the process and re-running your print statement
<BW^->right
<BW^->and shift/reset does.. ?
<turbofail>because it captured the whole continuation. it means you can't ever really capture any value that you might have wanted to return from that "suspended process"
<turbofail>well i mean you can, but you have to use some ugly set! tricks
<BW^->turbo: like, double call/cc:s ?
<turbofail>yeah, kind of
<turbofail>but just using 2 call/cc's doesn't cut it
<BW^->turbo: can you give me a minimum useful example of shift/reset ?
<BW^->that illustrates this?
<BW^->particular use of it
<BW^->just to get it :))
<turbofail>well this is a minimum useful example
<turbofail>you can the shift/reset continuation as many times as you want without losing track of it
<turbofail>from anywhere
<BW^->mhm
<turbofail>but another example is, let's say you're mapping over a list, but you want to be able to take a break in the middle of it for some reason
<BW^->turbofail: so the shift/reset continuation is "delimited" in that it won't capture more than up to the point where it was made??
<turbofail>yes, the reset delimits the point up to which is captured
<turbofail>anyway back to the map example, you could do (define foo (reset (map (lambda (x) (shift k (vector x k))) my-list)))
<BW^->aha?
<turbofail>and this would return a vector containing the first element of the list, and a continuation that you can supply a new value to
<turbofail>upon supplying that new value, you'd get back the next element of the list and a new continuation
<BW^->hmhm
<BW^->mhm
<turbofail>this basically turns `map' into a resumable iterator over a list
<BW^->okay, that's neat
<BW^->turbofail: i'm 100% sure call/cc can be used for this
<turbofail>you can, but it's a lot more difficult
<BW^->but sure, this code you suggested now is a slightly shorter route for that purpose
<turbofail>and like i said, you'll have to resort to some set! trickery
<turbofail>trust me i've done it
<BW^->turbofail: i would think shift/reset can be implemented in terms of call/cc?
<turbofail>it's much harder to get right
<turbofail>perhaps it can, but it's not a good way to implement it
<turbofail>regardless it could only ever be the same on a single-threaded system, as the call/cc implementation would make heavy use of mutation
<turbofail>the other important point is that the map iterator that we returned here is pure - you can restart it at any point just by saving an earlier continuation
<Chaos`Eternal>helo guilers
<turbofail>you might be able to fake such a thing with the call/cc/set! hackery, but i don't remember if i was able to do it completely
<turbofail>anyway, call/cc is certainly wrong for green threads. threads shouldn't include the portion of the call stack that created them
<turbofail>also, fun fact, the naive implementation of this map iterator using call/cc only works at the REPL because the continuation is already getting delimited by your scheme implementation
<turbofail>otherwise it turns into an infinite loop
<BW^->hm
<BW^->turbofail: so the shift/reset "continuation" keeps an "address pointer" for you?
<turbofail>well "naive" meaning "completely wrong" in this case
<BW^->(whereas for call/cc, reinvocations of k *always lead to the same address*)?
<turbofail>sure. you could think of it as, delimited continuations accept an extra "return continuation" that they use instead of the one they captured initially
<BW^->mhm
<BW^->turbofail: so I see reset/shift as a special-case of call/cc
<turbofail>if you were implementing a scheme compiler in continuation passing style, you would use 2 continuation arguments insetad of one in order to implement delimited continuations
<BW^->ouh
<BW^->okay, why?
<BW^->turbofail: you mean, at the fundamental CPS transformation level?
<turbofail>yes
<turbofail>because that's pretty much how the semantics of it work
<BW^->mhm
<turbofail>it's not really a special case, it's more like call/cc is just a special case of shift/reset with a reset enclosing the whole program
<BW^->turbofail: ok, so if I have ana rbitrary scheme implementation with call/cc support,
<BW^->turbofail: if I want to implement shift/reset I need to add an extra continuation argument for this into the CPS transformation
<BW^->turbofail: mhm
<turbofail>well many scheme compilers don't do a CPS transformation at all
<BW^->turbofail: those without call/cc, right.
<BW^->turbofail: like, Kawa.
<turbofail>no, plenty of them with call/cc still don't do a CPS transformation
<BW^->turbofail: but what do they do?
<turbofail>guile doesn't
<turbofail>racket doesn't
<turbofail>they just copy the stack
<BW^->turbofail: ouch
<BW^->turbofail: isn't that expensive?
<turbofail>yes
<BW^->turbofail: ouch.
<BW^->turbofail: what's the reasoning, that shift and call/cc is rare
<turbofail>yeah
<BW^->turbofail: but execution of CPS-transformed code is not expensive is it?
<BW^->it's rather a question of cost during compilation..??
<turbofail>bbl i have to go
<BW^->oki
<BW^->turbofail: ok, thanks for the conversation
<BW^->hm
<BW^->turbofail: wait - call/cc is not completely a special case of shift/reset
<BW^->because
<BW^->shift/reset has an updating address pointer in it, no?
<BW^->so sure, call/cc could be counted as a shift/reset with a reset around the whole program
<BW^->but
<BW^->shift/reset can also be implemented in terms of call/cc, and then that wrapper would implement the address pointer part too.
<nalaginrut>morning guilers~
***BW^- is now known as BW^-_
***BW^-_ is now known as BW^-
<cmhobbs>can someone point me to examples of standalone guile applications (read: not extensions)?
<nalaginrut>cmhobbs: #! /usr/bin/env guile
<cmhobbs>ha
<nalaginrut>cmhobbs: this is an example of standalone https://github.com/NalaGinrut/artanis/blob/wip-sql-mapping/examples/blog2.scm
<cmhobbs>thank you
<nalaginrut>cmhobbs: but I'm not sure if you need a standalone program included Guile static linked?
<cmhobbs>i was just interested in examples that could be executed as is
<nalaginrut>alright ;-)
<cmhobbs>and i just discovered the examples/ directory in the source
*cmhobbs headdesk
<ArneBab>BW^-: for CPS, have a look at the writeupo of wingo: http://wingolog.org/archives/2014/01/12/a-continuation-passing-style-intermediate-language-for-guile
<turbofail>BW^-: shift/reset doesn't have to have any sort of "updating address pointer," unless you count a normal procedure call as having one. it behaves more like a regular procedure call in that it simply returns to the caller
<turbofail>which is what i was getting at when i said you're "transplanting part of the call stack"
<turbofail>anyway the discussion of whether call/cc can implement shift/reset is kind of irrelevant because the fact remains that it is a bad way to do it
<ArneBab>turbofail: I guess you mean that it has disadvantages, right?
<ArneBab>(calling something “a bad way to do it” doesn’t sound like a strong argument)
<ArneBab>turbofail: like the threading
<ArneBab>sneek: later tell davexunit: I think I should have used your coroutine for the wisp reader. That would likely have been much cleaner: Create a function which only gets new expressions when the list of unprocessed expressions is empty.
<sneek>Okay.
<ArneBab>sneek: botsnack
<sneek>:)
<bipt>ArneBab, http://okmij.org/ftp/continuations/against-callcc.html links to some good arguments against call/cc in general
<ArneBab>bipt: thanks!
<ArneBab>sneek: later tell BW^-: <bipt> ArneBab, http://okmij.org/ftp/continuations/against-callcc.html links to some good arguments against call/cc in general
<sneek>Got it.
<turbofail>ArneBab: yeah. to me those two phrases mean the same thing. but anyway, that link that bipt gave pretty much summarizes all those disadvantages
<ArneBab>ok :)
<nalaginrut>I wonder if lambda-calculus based IR can be used for imperative-languages anyway, although it's proper for FP in natural
<nalaginrut>I wish it could, for multi-lang purpose
<nalaginrut>I saw Appel's paper said "they are both doing exactly same thing in different notation"
<civodul>Hello Guilers!
<nalaginrut>heya
*davexunit just used guile and guile-curl to do some FSF work :)
<davexunit>just a small import script that makes some http api calls, but still fun.
<sneek>davexunit, you have 1 message.
<sneek>davexunit, ArneBab says: I think I should have used your coroutine for the wisp reader. That would likely have been much cleaner: Create a function which only gets new expressions when the list of unprocessed expressions is empty.
<davexunit>ArneBab: hmmm, coroutines for a reader. interesting.
<davexunit>ArneBab: The (system repl coop-server) module in guile 2.0.11 uses prompts (what my coroutines are made from) to implement a REPL server.
<davexunit>maybe reading it would be useful to you
<dsmith-work>Morning Greetings, Guilers
<civodul>davexunit: yay for Guile at the FSF! :-)
<civodul>keep doing it, so they'll have to hire you forever ;-)
<davexunit>civodul: I'm only using it for one-off things right now, because I can write scheme 1000x faster than php or whatever.
<unknown_lamer>hey, does guile consider \\r a newline for buffer flushing
<unknown_lamer>also, hrm
<unknown_lamer>are signals delivered to guile threads via asyncs? I have a critical section where I am spitting data out to a serial port and a partial message will cause my program to permanently desync
<unknown_lamer>I've ... managed to create a workaround (kill function that locks the serial port lock before killing), but it is a paaaaain when hitting C-c in the repl during testing
<cky>unknown_lamer: I have an even better workaround for you. It's called SIG_IGN. :trollface:
<unknown_lamer>I should probably make my microcontroller code more robust :(
<dsmith-work>unknown_lamer: Which micro?
<unknown_lamer>was an arduino uno, and is now a teensy 3.1 (better pwm)
<dsmith-work>unknown_lamer: I've been living in PIC 23H land for the last 6 months.
<dsmith-work>24H
<unknown_lamer>the arduino was fun
<unknown_lamer>had to count bytes at one point :)
<dsmith-work>Heh
<unknown_lamer>with 64K of RAM on this teensy 3.1...
<unknown_lamer>infinite memory!
<dsmith-work>Indeed.
<dsmith-work>I worked on a micro with 2K of program flash, and 128 bytes of ram. And half of that was stack. 64K is a luxury at that level.
<dsmith-work>unknown_lamer: The cool thing is you own the machine down to the last bit.
<unknown_lamer>yes, it has been pretty fun
<unknown_lamer>even microcontroller programming lite (arduino libs...)
<unknown_lamer>I think I can run armpit scheme on the teesny actually
<unknown_lamer>needs some porting (afaict, register defs
<unknown_lamer>)
<taylanub>scheme@(guile-user)> (list-matches (make-regexp "foo$" regexp/extended) "foo\\n")
<taylanub>$8 = ()
<taylanub>scheme@(guile-user)> (list-matches (make-regexp "foo\\n$" regexp/extended) "foo\\n")
<taylanub>$9 = (#("foo\\n" (0 . 4)))
<taylanub>Bug or feature?
<taylanub>never mind. I needed `regexp/newline' as an argument to `make-regexp'.
<dsmith-work>taylanub: Anytime!
<taylanub>I need a channel full of rubber ducks. :)
*sneek quacks
<paroneayea>sneek: :)
<paroneayea>sneek: botsnack
<sneek>:)
<ArneBab>Is there a way to auto-parallelize list-ec (from SRFI-42)
<ArneBab>?
<ArneBab>davexunit: ah, nice!
<ArneBab>I just implemented my first ensemble square root filter in Guile - function parameter estimation from uncertain measurements.
<ArneBab>But I have lots of list-ec calls in there, and I’d like to make them multithreaded :)
<ArneBab>(ideally without lots of work…)
<cky>That depends on whether Guile has a thread pool system built in. If so, making a thread pool implementation of eager comprehensions shouldn't be too onerous.
<ArneBab>cky: how can I check that?
<civodul>(ice-9 futures) uses a thread pool
<civodul>par-map uses (ice-9 futures)
<civodul>but ISTR there's an open bug in that area...
<ArneBab>civodul: then I’d better delay that till tomorrow…
<ArneBab>here’s the new Ensemble Square Root Filter: https://bitbucket.org/ArneBab/wisp/src/1f2f784f4785d86787856a9d5c8a8bfb182edcb1/examples/ensemble-estimation.w
<civodul>did you try to get Geiser support for wisp?
<ArneBab>(it’s a simpler version of the EnSRF described by Peters et. al 2005: http://onlinelibrary.wiley.com/doi/10.1029/2005JD006157/abstract
<ArneBab>civodul: not yet - I’d like to get the SRFI done first.
<civodul>ok
<ArneBab>civodul: also I need to find a way to store the line-numbers when reading the file (I know it’s possible, I just didn’t manage to do it yet)
<ArneBab>(and didn’t have the time)
<civodul>yeah, source properties
<ArneBab>see you tomorrow