IRC channel logs


back to list of logs

<wleslie>Good morning, guilers!
<jyc>I'm trying to compile Guile from source and it seems to be taking a long time at the GUILEC ice-9/eval.go point :P
<jyc>I did some Googling and it looks like this is supposed to take a while to finish
<jyc>What is it doing during that makes this take so long?
<mark_weaver>jyc: it's running the compiler in a slow interpreter to compile the compiler.
<jyc>mark_weaver: Haha, I see. Thanks
<mark_weaver>basically it's a bootstrapping issue. as the bootstrap proceeds, and more modules of the compiler have been compiled, it will become progressively faster
<daviid`>jyc: just to be sure: guile's master branch, the 1 you get when you git clone, is actually the developers branch, where they work on future major release, guile-2.2. if what you want is the latest stable, you should checkout the stable-2.0 branch instead. stable-2.0 also compiles a lot faster
<jyc>daviid`, I see, thanks
<nalaginrut>morning guilers~
<artyom-poptsov>Hello nalaginrut
<ArneBab_>mark_weaver: would it be doable to adjust the makefiles such that -j N starts with the files which impose the most heavy performance penalty to speed up the compile?
<amz3>héllo :)
<nalaginrut>ArneBab_: maybe it's hard, since the most heavy module is the first two, 9-boot and eval
<nalaginrut>and they're the dependencies of all modules
<ArneBab_>nalaginrut: that means if all modules would depend explicitly on 9-boot.go and eval.go, they would always be built before any other gets started.
<ArneBab_>the two
<ArneBab_>for non-parallel builds this is already optimized, but parallel builds break the order.
<nalaginrut>parallel compiling for Guile program needs some proper handling, Artanis has problems with 'make -j n', the problem is there's always module didn't build
<__uu__>no babel support for guile in emacs orgmode?
<__uu__>never mind, figured it out
<zacts>hi guilers
<ArneBab_>are there Scheme modules which exploit that (let ((a b)(cd))) does not define an ordering to provide automatic parallelization?
<wleslie>no, because it's not sufficient for parallelisation
<wleslie>evaluation of b and d may still have conflicting effects
<wleslie>while their order is not specified, it is specified that one runs to completion before the other begins, iirc
<ArneBab_>why then is there a let* form?
<ArneBab_>(what’s the advantage of having the plain let?)
<wleslie>it's more useful if the value is a function
<mark_weaver>ArneBab_: even without parallelization, allowing the compiler to choose the order can sometimes allow better optimization.
<wleslie>because it controls what ends up in the closure of the function
<mark_weaver>also, sometimes 'let' is useful precisely because earlier bindings don't shadow later ones.
<mark_weaver>and 'let*' is actually defined in terms of 'let'.
<mark_weaver>and things like named-let don't actually make sense as let*
<wleslie>it's like (let [...] (let [...] ...))
<ArneBab_>ah, so I can rely on (let ((a 1)) (let ((a 2)(b a)) b) to return 1?
<mark_weaver>'let' is equivalent to a single 'lambda' and procedure call, whereas 'let*' is equivalent to a bunch of nested 'lambda's and procedure calls.
<mark_weaver>ArneBab_: yes
<ArneBab_>is let* significantly slower?
<mark_weaver>it depends on the implementation I suppose
<ArneBab_>why doesn’t named let make sense as let*? I’d think that that would simply be an initialization with let*
<mark_weaver>at present, we don't take advantage of the freedom that 'let' gives us as much as we could.
<mark_weaver>named-let gives a name to the single procedure that 'let' uses internally.
<mark_weaver>(let ((v1 e1) (v2 e2)) body) is equivalent to ((lambda (v1 v2) body) e1 e2)
<mark_weaver>named-let simply gives a name to the procedure that 'lambda' creates.
<mark_weaver>but (let ((v1 e1) (v2 e2)) body) is equivalent to (let ((v1 e1)) (let ((v2 e2)) body)) which is equivalent to ((lambda (v1) ((lambda (v2) body) e2)) e1)
<mark_weaver>and nowhere in there is a procedure that would be suitable for continuing the loop.
<ArneBab_>let*, right?
<mark_weaver>ah, right, that first 'let' in my second-to-last message should be 'let*'
<mark_weaver>anyway, the meanings of 'let' and 'let*' have been like this for at least 30 years, and not something that we can change without breaking a lot of code.
<mark_weaver>(understatement of the year :)
<wleslie>but we might have some better effect analysis in the future.
<ArneBab_>I’d have thought that (let* loop ((v1 e1)(v2 e2))) would transform into something like (let* ((v1 e1)(v2 e2)) (let loop ((w1 v1)(w2 v2)))
<ArneBab_>I’m just trying to understand the deeper possibilities from let, not to change what is already there.
<ArneBab_>and trying to find out why I should use let as opposed to let*
<ArneBab_>(☺ to understatement)
<mark_weaver>ArneBab_: something like that would be feasible, although 'w1' and 'w2' would have to be renamed to 'v1' and 'v2', but the resulting code is a lot more complex.
<mark_weaver>(the reason is that 'body' may refer to 'v1' and 'v2')
<ArneBab_>ah, yes
<ArneBab_>so the intermediate let* would have to use placeholder names
<ArneBab_>no pattern for named let*… I wonder how long it would take… ☺
<mark_weaver>ArneBab_: no, they could use all the same names.
<ArneBab_>ah, yes, because let shadows them
<mark_weaver>(let* loop ((v1 e1) (v2 e2)) body) could expand to (let* ((v1 e1) (v2 e2)) (let loop ((v1 v1) (v2 v2)) body))
<mark_weaver>another example of why 'let' is useful for its "parallel" binding. (not parallel execution)
<ArneBab_>yes :)
<ArneBab_>ACTION is happy 
<dsmith-work>Monday Greetings, Guilers
<artyom-poptsov>Evening greetings, dsmith-work
<paroneayea>hello, *!
<ArneBab_>mark_weaver: can I use syntax-case to redefine let* and within than redefinition access the original let*?
<mark_weaver>ArneBab_: no.
<mark_weaver>however, there are some easy options
<mark_weaver>the most general way is to define it using a different name in its own module, and then rename it on export.
<mark_weaver>so, maybe call it 'let*+' and then export it as 'let*'
<ArneBab_>so like (define-module (named-letstar) #:export ((named-let* . let*)))?
<ArneBab_>then all that’s left is getting this syntax-case form right…
<mark_weaver>no need for syntax-case. syntax-rules should be good enough for this.
<ArneBab_>I wanted to try syntax-case, but I’m failing…
<ArneBab_>I’ll try it with syntax-rules
<mark_weaver>ArneBab_: you'd better put the non-named-let case first
<ArneBab_>… that allows me to avoid checking for identifier? stuff… the problem just became much easier… thanks!
<ArneBab_>hm, it seems to work…
<ArneBab_>ok, that’s absolutely crazy — named let* works ☺
<ArneBab_>that’s 8 lines of code from “why doesn’t that work” to “it works!”
<ArneBab_>mark_weaver: thank you!
<mark_weaver>ArneBab_: yw!
<ArneBab_>now, how to go on from here? ☺
<ArneBab_>(damn, need to go… maybe I’ll ask on guile-devel…)
<amz3>I have great news!! I discovered `when` and it's awesome
<wlhlm>Hi, I have a problem on Mac with shared objects that are linked with libguile. Basically when I try to unload such a shared object, a segfault gets triggered on dlclose. It would be great if someone on Mac can try to reproduce it. Here's a guide:
<amz3>(how do you use mac keyboard? fame?)
<taylanub>wlhlm: I think I'm one of the few if not only regular or semi-regulars who has access to OS X (at work in my case). I can try it tomorrow if it's easy to follow your instructions
<wlhlm>taylanub: that would be great! I'm currently trying to build guile with some debug information to get a proper backtrace, but it takes ages on my machine. I'll open a bug report, I think.
<taylanub>ACTION puts it on the todo
<mark_weaver>wlhlm: I'm not entirely sure that we support unloading shared objects linked to libguile. typically, such shared objects will add procedures and variables to guile, which I guess means that pointers from guile global data structures will point into the shared object.
<mark_weaver>I'm also not sure how bdw-gc, the garbage collector used by libguile, copes with this. it has some magic to add all global variables to the GC roots, and that must include globals from shared objects. if the shared object is later unmapped, I don't know if it has the necessary logic to handle that properly.
<wlhlm>The issue originally occured with weechat, which provides a guile scripting interface via a dynamically loaded plugin (shared object).
<wlhlm>mark_weaver: From the backtrace it looks like one of atexit() handlers is at fault here. Looking at the guile source, there isn't anythng noteworthy, so I guess that the gc is causing the issue.
<mark_weaver>honestly, I suspect that neither bdw-gc nor libguile have been designed to be unloaded from a process.
<mark_weaver>ditto for libraries linked with libguile
<mark_weaver>I'd be curious to hear civodul's take on this
<mark_weaver>civodul ??
<mark_weaver>sorry, one '?' would have been sufficient there :)
<mark_weaver>civodul: wlhlm reports: <wlhlm> Hi, I have a problem on Mac with shared objects that are linked with libguile. Basically when I try to unload such a shared object, a segfault gets triggered on dlclose. [...]
<civodul>where's the backtrace?
<civodul>i thought nobody uses dlclose ;-)
<civodul>hmm hard to tell
<civodul>there aren't many details here
<civodul>wlhlm: could you try something with scm_with_guile instead of scm_init_guile?
<wlhlm>civodul: sure, sec.
<wlhlm>civodul: I get the same backtrace. Since the segfault is triggered during unload, I guess that one of the atexit() handlers is the cause. I think that it's the garbage collector, but I have to investigate further.
<civodul>wlhlm: yes perhaps it would make sense to try the same using just libgc instead of libguile