IRC channel logs


back to list of logs

<calher>davexunit: I can't scp the generated site/ directory to a server and have it work, because the links it generates are not relative -- it assumes that the files are at /.
<calher>davexunit: See for an example.
<ijp>I'm pretty pleased with this bignum library I'm hacking
<zv>i just got my mind blown by (let ((a 1)) (define (f x) (define b (+ a x)) (define a 5) (+ a b)) (f 10))
<zv>i've been programming for years and i would have never guessed...
<ijp>that should be an error
<zv>in guile its 20
<zv>in racket its an error
<ijp>I think it's an optimiser bug
<zv>i mean, 16, 20 and "error" are all valid in some way -- wouldn't you say?
<ijp>because I know how letrec* is defined
<zv>"couldn't find source for letrec*" :(
<ijp>it's handled in the macroexpander
<ijp>anyway, the outer let is a red herring for this one
<zv>what do you mean?
<zv>shouldn't that bind the definition of let?
<ijp>rename the outer a to c and you get the same result
<zv>that is wild
<ijp>I guess this falls in the category of wrong bug harmless
<zv>whats going on there?
<ijp>zv: if it didn't, you wouldn't be able to have recursive inner defines
<zv>inner defines meaning... letrec?
<ijp>I say harmless because if you replace the value of a with (launch-the-missiles 5) you get the right answer
<ijp>namely an error
<zv>i see
<zv>i mean, i dont really see
<zv>but thats interesting at least
<zv>compiling guile to see if i can get emacs to source the letrec* definition in guile so i can see what you are talking about
<ijp>that isn't going to help you very much
<ijp>geiser won't find the definition because it's part of the expander
<ijp>and the expander isn't very clear to begin with
<zv>so what is a at the top of the body of "f"
<zv>is it "undefined"? is it "null"
<ijp>it is irrelevant
<ijp>wait, sorry, wrong 'a'
<zv>although that sounded cool
<zv>"wrong, it is *IRRELEVANT*"
<ijp>it is undefined, although strictlyf speaking guile should probably error when it is accessed
<zv>anyway, i see what you mean, changing the varname of `a' to anything else preserves the structure of the code
<zv>so why do I get 20?
<zv>clearly the "define" is being moved to the beginning of the stack frame
<zv>rather, the value is.
<ijp>in effect yes
<ijp>probably during the "fixing letrec" pass
<ijp>ACTION whistles innocently
<zv>ijp are you alive
<lloda>meep seems to be one of the big Guile users, but we don't see them around too much. I got into Guile through libctl and one day I just had to remove the whole thing. Ah those evil define-macros...
***cluck` is now known as cluck
***cluck`` is now known as cluck
<zv>is there any way to have a function run at the end of compilation/interpretation without actually having a function at the end of the file?
<mark_weaver>zv: it doesn't matter where the procedure definition is, but if you want to run it at the end, then you need to *call* that procedure at the end of the module.
<zv>thanks mark_weaver
<zv>maybe you could answer one more question
<zv>why does this print 20? (let ((a 1)) (define (f x) (define b (+ a x)) (define a 5) (+ a b)) (f 10))
<zv>in guile
<mark_weaver>I saw that discussion earlier.
<zv>ijp tried to answer it but he just said there was some macroing going on
<zv>i tried to look into it and it's above my pay grade to be honest
<mark_weaver>at the expression (+ a x), the 'a' that is in scope there is the inner 'a', which is defined to be 5.
<mark_weaver>the outer 'a' is not actually referenced from anywhere in that case.
<zv>by a has not yet been defined?
<mark_weaver>well, they are two different variables, despite having the same name.
<mark_weaver>now, technically you have violated a restriction of letrec there, by referencing 'a' before it is initialized.
<zv>but then isn't the (+ a b) referencing an a that doesn't exist?
<mark_weaver>the inner binding of 'a' that it references does exist, but according to the semantics of letrec*, it has not yet been initialized.
<mark_weaver>now, our optimizer clearly did some rearranging there, to perform the initialization of 'a' before the initialization of 'b'.
<mark_weaver>it would have been better to detect and raise an error here, but that's not required.
<zv>i see
<mark_weaver>if you want to reference the outer 'a', then you should use 'let' instead of inner defines.
<mark_weaver>because a block containing internal 'defines' is equivalent to a 'letrec*', where all the inner definitions are in scope in all of the right-hand-side initializers.
<mark_weaver>however, you are not allowed to forward reference variables in those right-hand-side initializers.
<mark_weaver>if you do, the results are unspecified.
<mark_weaver>what you *are* allowed to do is to forward reference variables from within *procedures* that are not called immediately, and that's the typical use: to define a set of mutually recursive procedures.
<mark_weaver>e.g. (let ((a 1)) (define (f x) (define (b) (+ a x))
<mark_weaver> (define a 5) (+ a (b))) (f 10))
<mark_weaver>actually, it turns out that our optimizer simply evaluates that entire piece of code into a constant, 20.
<mark_weaver>as shown by: ,optimize (let ((a 1)) (define (f x) (define b (+ a x)) (define a 5) (+ a b)) (f 10))
<zv>oh wow
<zv>are there any tools that show the steps and logic of the optimizer?
<mark_weaver>well, the REPL has commands for viewing the output of macro expansion (,expand) and partial evaluation (,optimize)
<mark_weaver>but we don't have anything that shows the individual steps and explains them.
<mark_weaver>but most of the optimizers are in module/language/tree-il/*.scm
<mark_weaver>and has quite a few blog posts about aspects of guile's compiler and optimizers.
<mark_weaver>in the master branch (2.1+) much of the newer optimizations are in module/language/cps/*.scm