IRC channel logs

2013-11-29.log

back to list of logs

<nalaginrut>morning guilers~
<nalaginrut>Is there any method to define var in toplevel in a function? except module-define! ?
<nalaginrut>if no, I'll pick module-define!
<gjanssens>I have a c string representing a function to be called
<gjanssens>How can I convert it into an SCM object without it being evaluated on the spot
<gjanssens>(so scm_c_eval_string is not useful here)
<gjanssens>I want this scm function to be passed to call-with-error-handling
<gjanssens>If the c string has errors, a simple scm_c_eval_string will throw before I can pass the function to call-with-error-handling
*gjanssens will try scm_from_utf8_string...
<nalaginrut>gjanssens: can you describe it in detail? do you want to convert "func" to a Scheme function named 'func'? or you just want to eval a string?
<gjanssens>The c string is this ""(gnc:report-run 6)"
<gjanssens>gnc:report-run is a scheme function
<gjanssens>6 is a variable number, it can be different with each run
<gjanssens>In c, I'm running scm_call (<scm ref to call-with-error-handling>, <my-c-string-converted-to-guile>, some-other-args)
<gjanssens>I know how to get the scm ref to call-with-error-handling,
<gjanssens>I'm not sure what to pass as thunk to this function
<gjanssens>If I pass scm_from_utf8_string ("(gnc:report-run 6)"), will that be evaluated as a function to call ?
<gjanssens>Or will it bail out with an error because an scm string is not an scm function ?
<gjanssens>Got error: unknown keyword :(
<gjanssens>Here is my function call:
<gjanssens> result = scm_call (scm_variable_ref (catch_func), // error handling wrapper
<gjanssens> scm_from_utf8_string (str), // actual function to evaluate
<gjanssens> scm_from_utf8_string ("#:on-error 'backtrace"),
<gjanssens> scm_from_utf8_string ("#:post-error 'report"),
<gjanssens> SCM_UNDEFINED);
<gjanssens>catch_func is the call-with-error-handling looked up via scm_s_public_lookup
<gjanssens>getting that function seems to work just fine
<gjanssens>somewhere in my argument passing it goes wrong
<nalaginrut>gjanssens: scm_from_utf8_string ("(gnc:report-run 6)") won't be treated as a function call, it's a Scheme string
<nalaginrut>scm_call(..., scm_from_utf8_string("#:on-error 'backtrace") ... is not correct, you just passed a bunch of strings into your function
<nalaginrut>not valid keywords options as you wish
<gjanssens>nalaginrut: that's what I feared
<gjanssens>any pointers for proper function and keyword passing ?
<gjanssens>got the keywords figured out
<gjanssens>now only the function call still
<gjanssens>wingo: I'm struggling with call-with-error-handling in c code
<gjanssens>do you read the backlogs of the irc channel or should I rather repeat my question ?
<gjanssens>the summary is rather short, I'll just repeat
<gjanssens>I want to wrap a scheme call with call-with-error-handling, but in c code
<gjanssens>a couple of days back you pointed me in the right direction
<gjanssens>But I'm stuck on one small detail
<gjanssens>the scheme function only exists on the c side as an ordinary string: "(gnc:report-run 6)"
<gjanssens>I'm trying to convert that string in a scheme function to pass as thunk to call-with-error-handler
<gjanssens>I first looked at scm_c_eval_string, but that doesn't return a function, it evaluates the string and returns the result
<gjanssens>And if the evaluation itself fails, it's not wrapped with an error handler.
<gjanssens>That's the point of trying to evaluate the function only within call-with-error-handler
<gjanssens>So I am looking for a function similar to scm_from_utf8_string or scm_from_utf8_symbol, but then for a procedure...
*gjanssens may be a bit naive here though
<gjanssens>thinking further on my issue
*gjanssens is off to try something else once more...
<gjanssens>sigh... I don't see it
<gjanssens>I can make an SCM function with scm_c_define_gsubr
<gjanssens>But since my string is a combination of a function and an argument (which can have a different value each time the function is called)
<gjanssens>that won't work
*gjanssens read about scm_thunk_p, and realizes call-with-error-handling needs a thunk
<gjanssens>what I'm trying to pass is not a thunk (ie a procedure without arguments)
<gjanssens>are there c side functions to create a thunk ?
<gjanssens>I can either start from a c string or from an SCM procedure and and SCM argument list
<gjanssens>Which I'd like to wrap in one SCM procedure
<gjanssens>in scheme that's easy (program args) is already ok as thunk
<gjanssens>I don't see how to create an SCM object that can serve as a thunk in C though
<gjanssens>If I take the SCM procedure object and use scm_cons to append all the SCM arguments
<gjanssens>would that work ?
<dsmith>If you have the proc, can't you just use scm_call or scm_call_N ?
<gjanssens>because I want to wrap it in call-with-error-handling
<gjanssens>I'm already using scm_call to run call-with-error-handling
<gjanssens>and I need to pass a function argument
<gjanssens>I mean, I need to pass it a procedure as argument
<gjanssens>But I don't know how to pass the arguments for the procedure itself
<gjanssens>as the documentation for call-with-error-handling say I need a "thunk"
<gjanssens>which I understand means a procedure that does not take arguments
<dsmith>Ah
<dsmith>Hmm. Maybe scm_c_catch would be better
<dsmith>IT's a lot more work. Doing closures in C is a bit more painful than in Scheme.
<gjanssens>I'm trying to replace the deprecated scm_stack_catch_internal functions we are still using
<gjanssens>The alternative approach I was considering was to write the whole function call as a c string
<gjanssens>and simply run scm_c_eval_string on that
<gjanssens>well, I got it working - sort of
<gjanssens>in the string scenario at least
<gjanssens>That is when the function I want to wrap initially only exists as a c string
<gjanssens>Take "(gnc:report-run 0)" as example
<gjanssens>I first wrap it in a define like so "(define (my_func)(gnc:report-run 0))"
<gjanssens>and I call scm_c_eval_string on this string to make my_func a function in the current environment
<gjanssens>then to get the SCM object for this function, I called scm_c_eval_string("my_func"), which returns the wanted object
<gjanssens>pfew
<gjanssens>I'm not sure it's 100% correct though
<gjanssens>Because I added a division by 0 somewhere in the code that gets run just to check
<gjanssens>and guile errors out with
<gjanssens>Exception thrown while printing backtrace:
<gjanssens>ERROR: In procedure display_backtrace_body: Wrong type argument in position 1 (expecting stack): #f
<gjanssens>so presumably I'm still doing something wrong
<gjanssens>And all this because I'm actually chasing another issue, which I thought might have been due to scm__stack_catch_internal
<gjanssens>This experiment at least shows it's not
<gjanssens>because with scm_stack_catch_internal out of the way it still fails
<gjanssens>So I'll just drop the call-with-error-handling thing for now and pursue other options
<gjanssens>I may come back later to this...
<davexunit>hello guilers
<sneek>Welcome back davexunit, you have 1 message.
<sneek>davexunit, unknown_lamer says: you might want to look at http://www.haskell.org/haskellwiki/Frag regarding FRP (the thesis paper associated is great, and notes a few pain points with normal FRP that they found solutions for)
<davexunit>unknown_lamer: thanks
<mark_weaver>gjanssens: are you still here? I can help with your problem.
<gjanssens>mark_weaver: yes
<mark_weaver>the argument to 'call-with-error-handling' is a 'thunk', which means a procedure that takes no arguments.
<mark_weaver>so you need to construct a SCM procedure that evaluates the string.
<gjanssens>isn't that what I did when I evaluated "(define (my_func)(gnc:report-run 0))" ?
<gjanssens>I passed that as argument to scm_c_eval_string
<mark_weaver>sorry, I haven't read the entire backlog, just part of it.
<gjanssens>np
<mark_weaver>one way to create such a procedure is to construct the list structure (lambda () (eval-string <string>))
<mark_weaver>and then evaluate that to create a procedure that, when called, with evaluate the string.
<gjanssens>you mean I should call scm_c_eval_string on that and the return value will be an SCM procedure ?
<mark_weaver>yes.
<gjanssens>Ah, I was close then :)
*gjanssens will test this right away
<mark_weaver>so that would be something like: scm_primitive_eval (scm_list_3 (scm_from_utf8_string ("lambda"), SCM_EOL, scm_list_2 (scm_from_utf8_string ("eval-string"), scm_from_utf8_string (<your string>))));
<mark_weaver>(that's untested)
<mark_weaver>even if your string has errors, that should always return a procedure.
<gjanssens>cool
<mark_weaver>the return value of that 'scm_primitive_eval' can be passed as the 'thunk' to 'call-with-error-handling'.
<mark_weaver>you'll need to import '(use-modules (ice-9 eval-string)' to get the binding 'eval-string'.
<mark_weaver>personally, I'd do more of this from Scheme and less from C.
<mark_weaver>for example, you could define, from Scheme, a procedure that takes care of all of this, and then just call it from C with your string.
<mark_weaver>so, from Scheme you could have (define (eval-string-with-error-handling str) (call-with-error-handling (lambda () (eval-string str)) <keyword args here>...))
<mark_weaver>and then from C, all you'd have to do is call 'scm_call_1' with the procedure object for 'call-with-error-handling' (which could be fetched just once during initialization), and the argument would be your string, converted to SCM using scm_from_utf8_string. (or maybe scm_from_locale_string depending on the origin of your C string)
<mark_weaver>more specifically, it would be: scm_call_1 (scm_c_public_ref ("eval-string-with-error-handling", "MODULE NAME HERE"), scm_from_?_string (<THE_STRING>))
<gjanssens>ok
<gjanssens>call-with-error-handling is new in guile 2 right ?
<mark_weaver>yes
<mark_weaver>so, in your scheme code, you could use 'cond-expand' to use a different implementation for guile 1.8, if you need to still support that.
<gjanssens>guile 1.8 can continue to use scm_stack_catch_internal
<gjanssens>but in guile 2 that's deprecated
<gjanssens>so a cond-expand will do just fine
<mark_weaver>it would look something like (cond-expand (guile-2 (define (eval-string-with-error-handling str) (call-with-error-handling (lambda () (eval-string str)) <keyword args here>...))) (guile (define (eval-string-with-error-handling str) <guile-1.8 code>)))
<mark_weaver>(sorry for the lack of indentation :)
<gjanssens>np
<mark_weaver>(cond-expand
<mark_weaver> (guile-2
<mark_weaver> (define (eval-string-with-error-handling str)
<mark_weaver> (call-with-error-handling
<mark_weaver> (lambda () (eval-string str)) <keyword args here>...)))
<mark_weaver> (guile
<gjanssens>the reason most of this was in c is that in case of an exception the c code would extract the backtrace in print it nicely in a window
<mark_weaver> (define (eval-string-with-error-handling str)
<mark_weaver> <guile-1.8
<mark_weaver> code>)))
<mark_weaver>well, you can do that from Scheme also.
<gjanssens>Probably, but I didn't get to that point yet
<gjanssens>until now, I was playing with the keyword #:post-error 'report
<gjanssens>which prints the stack trace to stdout
<gjanssens>(probably to the current port is more correct)
<gjanssens>How can I catch instead/additionally and return it to the calling function ?
<wingo>(with-error-to-string (lambda () (call-with-error-handling ...))) i think
<wingo>that will throw away the normal return value of the thing you are calling though
*gjanssens gets dizzy from so many lambdas ;)
<wingo>:)
<gjanssens>will it onl y throw it away in case of an error or always ?
<mark_weaver>wingo: the problem is, 'call-with-error-handling' outputs the backtrace to the current output port, not the current error port. last I checked anyway.
<wingo>mark_weaver: humm!
<mark_weaver>oh, nevermind.
<gjanssens>ok, so I would get the result automatically
<mark_weaver>hmm, what made me think that?
<wingo>mark_weaver: i think you are right
<wingo>gjanssens: with-error-to-string only returns whatever you wrote to the current error port, nothing else
<mark_weaver>wingo: ah, if you pass #:on-error 'backtrace, then indeed the backtrace is printed the the current output port.
<mark_weaver>however, with #:on-error 'report, you only get the error message (no backtrace), and that is printed to the curent error port.
*wingo apologizes for strange interfaces
<mark_weaver>wingo: do you think we should fix this? I've had it on my TODO list for a while, but I'm afraid of code that might depend on our current weird behavior.
<mark_weaver>IMO, the backtrace should be printed to the current error port.
<mark_weaver>maybe we can fix it in master at least.
<wingo>mark_weaver: sure, certainly in master
<wingo>dunno if we can do so on stable-2.0
<wingo>i don't have much of an opinion on that fwiw
<mark_weaver>okay
<gjanssens>wingo: then with-error-to-string is not my function, at least not as you proposed
<gjanssens>gnucash depends on the normal output of the function I'm trying to error wrap
<wingo>gjanssens: i think you need to specify your function :)
<mark_weaver>gjanssens: do you want the backtrace, or just the error message?
<gjanssens>I'm comparing with code that was there (which I didn't write)
<gjanssens>it is supposed to be a convenient wrapper around scm_c_eval_string
<gjanssens>but in case of an error, it prints a backtrace using g_warning
<mark_weaver>ah, so if there's no error, then it should return the SCM result of that evaluation.
<gjanssens>(I was wrong about it being displayed in a window)
<gjanssens>yes
<mark_weaver>maybe the Scheme code should just call g_warning directly
<gjanssens>another thought: can I know if call-with-error-handling caught an exception or returned normally ?
<gjanssens>or is that completely transparent to the surrounding code ?
<mark_weaver>if there's an error, it returns the "unspecified value".
<mark_weaver>so what you could do is wrap the non-error return value in a list of one element, and test for that from C.
<mark_weaver>hmm, give me a minute to think this through.
<mark_weaver>will the evaluated code ever print anything to the current output or current error ports?
<gjanssens>I think so yes
<gjanssens>the evaluated code is supposed to generate an SCM string
<gjanssens>which is captured in the return value
<gjanssens>so I'd think it writes to the current output port
<mark_weaver>can you show me the code for this that was meant to work with guile 1.8 ?
<gjanssens> https://github.com/Gnucash/gnucash/blob/trunk/src/app-utils/gfec.c
<gjanssens>That's the source file defining the wrapper (look for gfec_eval_string)
<gjanssens>and it's called from here: https://github.com/Gnucash/gnucash/blob/trunk/src/report/report-system/gnc-report.c#L154
<gjanssens>that code expects to receive an SCM string or in case of an error, SCM_UNDEFINED
<mark_weaver>it may be that 'call-with-error-handling' is just not a good fit here.
<gjanssens>IMO the original author went through a lot of hoops for the 1.8 code already
<gjanssens>I just got to call-with-error-handling because that's what the deprecated message refers to
<gjanssens>(for scm_stack_catch_internal that is)
<mark_weaver>however, it doesn't look to me like the standard output is being captured here.
<mark_weaver>so that's probably not an issue.
<gjanssens>how is result set up then if not via standard output ?
<mark_weaver>it would be nice to simplify this code though.
<mark_weaver>well, the evaluated code simply returns the result.
<mark_weaver>do you want the scheme backtrace included in the error report?
<gjanssens>it's currently not, but I would consider that an improvement
<gjanssens>although, on second thoughts, perhaps users won't like it
<gjanssens>I'm not sure
<mark_weaver>okay, I'll leave it out for now.
<gjanssens>ok, if it ends up on stdout that's sufficient. stdout is captured in a separate log file anyway
<gjanssens>we can always ask the user for that log file if we want more details
<mark_weaver>(define (eval-string-with-error-handling str)
<mark_weaver> (call-with-current-continuation
<mark_weaver> (lambda (k)
<mark_weaver> (with-error-to-string
<mark_weaver> (lambda ()
<mark_weaver> (call-with-error-handling
<mark_weaver> (lambda () (k (list (eval-string str))))
<mark_weaver> #:on-error 'report
<mark_weaver> #:post-error 'catch
<mark_weaver> #:trap-handler 'disabled))))))
<mark_weaver>that will return one of two things: (1) a list containing a single element, the result of the successful evaluation, or (2) a string containing the error message.
<mark_weaver>from C you can use 'scm_is_string' to check if it's a string.
<mark_weaver>if it's not a string, it will be a list, in which case you get the return value using 'scm_car'
<gjanssens>thanks
<gjanssens>and will the backtrace be printed to stdout in case of an error ?
<mark_weaver>that code won't output a backtrace.
<mark_weaver>if you change 'report to 'backtrace, then it will output the backtrace to stdout, yes. we could arrange to capture that too if you like.
<mark_weaver>(and actually, you should be prepared for a likelihood that we'll fix this, so that the backtrace goes to the error port in some future version of guile)
<gjanssens>yes, I just read that
<mark_weaver>but if you want to include the backtrace in the string, then I can show you how to do that in such a way that will be future-proof.
<gjanssens>please do
<mark_weaver>okay, give me a minute
<gjanssens>I'll not that the #:on-error value of 'report is not documented
<gjanssens>and neither is 'backtrace
<gjanssens>s/I'll not/I'll note/
<gjanssens>'report is only documented as an option for #:post-error
<mark_weaver>(define (eval-string-with-error-handling str)
<mark_weaver> (call-with-current-continuation
<mark_weaver> (lambda (k)
<mark_weaver> (call-with-output-string
<mark_weaver> (lambda (p)
<mark_weaver> (with-output-to-port p
<mark_weaver> (lambda ()
<mark_weaver> (with-error-to-port p
<mark_weaver> (lambda ()
<mark_weaver> (call-with-error-handling
<mark_weaver> (lambda () (k (list (eval-string str))))
<mark_weaver> #:on-error 'backtrace
<mark_weaver> #:post-error 'catch
<mark_weaver> #:trap-handler 'disabled))))))))))
<mark_weaver>yeah, sorry that it's not completely documented.
<mark_weaver>admittedly, this is not a good fit for 'call-with-error-handling'.
*mark_weaver adds some items to his TODO list
<mark_weaver>ah, both of those are already on my TODO list :)
<gjanssens>heh :)
*gjanssens has been staring at the solution for some time now, but his head won't wrap around it
<gjanssens>I'll just trust you this is correct
<mark_weaver>I guess we should come up with a better API for error handling when the error message should be captured for display on a GUI.
<gjanssens>That is, I'll try with this and come back for more help if it doesn't work
<mark_weaver>well, the 'call-with-current-continuation' basically sets up a way to do a non-local return, kind of like a setjmp.
<mark_weaver>so calling (k <value>) will simply return <value> from the whole thing.
<gjanssens>like I said: to many lambda's makes my head turn :)
<gjanssens>ok
<gjanssens>and then the call-with-output-string together with with-output-to-port and with-error-to-port are meant to redirect standard output and standard error to a string
<gjanssens>right ?
<mark_weaver>right
<gjanssens>which is returned in case of an error
<gjanssens>while if there's no error the non-local exit path is chosen, so call-with-output-string is bypassed in that case
<mark_weaver>right. and if there's no error, then 'k' gets called which does a non-local exit out of all of that string-capturing stuff.
<gjanssens>powerful guile-fu
<gjanssens>you must be a black belt at that :)
<gjanssens>I hope you don't mind I set all this aside for a while and come back to it later
<mark_weaver>in this code, the lambda blocks are sort of analogous to blocks of code surrounded by curly braces that are like 'arguments' to C constructs such as
<gjanssens>I actually have a more pressing issue
<mark_weaver>'for' and 'if'.
<gjanssens>ok, that clears it up a lot
<gjanssens>I started this whole experiment because my "the-environment" issue from some time ago
<gjanssens>is acting up in some unexpected way
<mark_weaver>you have to wrap something in a lambda if you don't want the code to run immediately, or if you want it to run more than once.
<mark_weaver>ah, okay. tell me more.
<gjanssens>I thought it was perhaps due to the deprecated scm_stack_catch_internal, but it isn't
<gjanssens>we have some guile code that generates html reports
<gjanssens>some time ago I was here on the list trying to debug an ugly stack trace involving the-environment
<gjanssens>I got it fixed and thought that was it
<gjanssens>I mean, the current code works fine for guile 1.8 and guile 2 auto-compiled
<gjanssens>it turns out it doesn't work if we disable auto-compilation (and remove all the precompiled objects)
<gjanssens>In fact, in that context, guile seems to end up in an infinite loop
<gjanssens>So there's no crash, no back trace
<gjanssens>It just keeps on running forever
<gjanssens>but never returns
<gjanssens>No user action is possible anymore, except killing gnucash
<gjanssens>I did run gnucash in gdb to see where it loops, but didn't get any wiser
<gjanssens>the last call in gnucash code was the scm_stack_catch_internal function
<gjanssens>then it goes off into guile internals
<gjanssens>you see why I tried to replace scm_stack_catch_internal
<gjanssens>I have no idea how to debug this further
<mark_weaver>(sorry, had to step away for a bit; am now reading)
<mark_weaver>hmm
<mark_weaver>and what code was being evaluated within that scm_stack_catch_internal?
<mark_weaver>(the one that never returned)
<gjanssens>it starts with a call to (gnc:report-run <id>) to which I linked before:
<gjanssens> https://github.com/Gnucash/gnucash/blob/trunk/src/report/report-system/report.scm#L762
<mark_weaver>actually, if you can use this new code that generates the Scheme backtrace, it would be helpful to Ctrl-C when it's hung and then see the backtrace.
<gjanssens>ah ok
<gjanssens>currently ctrl-c doesn't do anything
<gjanssens>while hung
<gjanssens>I do note that gnc:report-run uses (backtrace-if-exception ...)
<mark_weaver>yeah, i noticed that too :)
<mark_weaver>how about kill -SIGINT <pid> ?
<gjanssens>so we're actually trying to catch backtraces twice :(
<mark_weaver>whenever I've looked at the code for big projects using libguile, it has always been very suboptimal code.
<gjanssens>I have it running in gdb currently, but I guess a backtrace from within the guile code would be more useful
<mark_weaver>I guess we need to improve our docs.
<mark_weaver>you could try this from within gdb: call scm_display_backtrace (scm_make_stack(0x404,0x304), scm_current_error_port (), 0x704, 0x704, 0x704)
<mark_weaver>(that's from the 'gdbinit' file which is in the top directory of the guile git repo)
<mark_weaver>(where it's bound to the command 'gbt')
<gjanssens>hmm, that command seems to hang as well
<mark_weaver>where is the code that uses 'the-environment', and what makes you think that the hang is related to that?
<gjanssens>because all other reports work fine
<gjanssens> https://github.com/Gnucash/gnucash/blob/trunk/src/report/business-reports/taxinvoice.scm
<gjanssens>I don't know actually that the fix for the-environment is causing this
<gjanssens>All I know is that this report is failing now
<mark_weaver>gjanssens: you might need to add 'expand' to the list passed to 'eval-when' on line 32.
<gjanssens>when running in interpreted mode on guile2
<gjanssens>before the fix it was failing in compiled mode and working in interpreted mode
<mark_weaver>(that might be the only problem)
<gjanssens>ok let me try that
<mark_weaver>well, even if that's the problem, there's at least one other problem here, namely that the error handling seems to be borked.
<gjanssens>adding expand doesn't fix it
<mark_weaver>hmm
<mark_weaver>I don't understand how, or why, 'the-environment' is being used here. I see no calls to 'local-eval'. I don't know what 'eguile-file-to-string' does. can you help me understand?
<gjanssens>eguile-file-to-string is defined here https://github.com/Gnucash/gnucash/blob/trunk/src/report/report-system/eguile-gnc.scm#L250
<gjanssens>the principle is that there is a template with a mixture of html and guile code
<gjanssens>taxinvoice.scm defines a number of parameters
<gjanssens>eguile-file-to-string is supposed to replace the guile markers in the template with the option values
<gjanssens>so the end result becomes a pure html file
<gjanssens>again not my code
<gjanssens>I only got involved in the guile part of gnucash because of guile 2 support
<mark_weaver>okay, makes sense
<gjanssens>(which may be considered quite reckless given my limited guile knowledge)
<gjanssens>but I'm learning every day :)
<mark_weaver>line 93 of eguile-gnc.scm should probably also have 'expand' in there. might be worth a try.
<mark_weaver>(adding 'expand' to both of those places)
<gjanssens>I did in the first try (forgot to mention, sorry)
<gjanssens>ok, the infinite loop is here: https://github.com/Gnucash/gnucash/blob/trunk/src/report/report-system/eguile-gnc.scm#L158
<gjanssens>I just added some debug output strings in various places
<gjanssens>the one I set there is printed in an infinite loop
<mark_weaver>ah, good, that was my next suggestion.
<mark_weaver>on line 158 I see a blank line
<gjanssens>?? isn't that line 156
<gjanssens>158 should be (define (loop...)
<mark_weaver>well, okay, i see the loop on line 160, but whatever :)
<mark_weaver>in (eq? line ""), the 'eq?' should be changed to 'equal?'
<mark_weaver>that might explain the infinite loop
<mark_weaver>when compiled, all instances of the same string literal will be the same object, but that's not necessarily the case when using the interpreter.
<mark_weaver>'eq?' tests pointer equality, essentially. it only reports true if the two objects are the same object.
<mark_weaver>it appears that in guile 1.8, all empty strings are the same object, but that's not the case in guile 2.
<gjanssens>this does end the infinite loop, yay !
<gjanssens>not there yet though
<gjanssens>I'm running into a backtrace
<gjanssens>but what surprises me is that it did work in compiled guile code
<gjanssens>only in interpreted mode it fails
<mark_weaver>the compiler does a little optimization that combines all equal string literals into the same object.
<mark_weaver>but that doesn't happen when compilation is turned off.
<gjanssens>okaay...
<gjanssens>that explains it obviously
<gjanssens>let me check what goes wrong now
<mark_weaver>oaky
<wingo>mark_weaver: o/~ did you ever know that you're my herooooo o/~ :)
<mark_weaver>wingo: aww, that's very sweet. you're one of my heroes too :)
<wingo>*group hug / high fives / appropriate forms of enthusiasm*
<mark_weaver>hehe
<gjanssens>LOL
<gjanssens>ok, the last backtrace was due to one badly placed debug statement
<gjanssens>now that I have removed it, the report works fine
<mark_weaver>nice! :)
<gjanssens>one final check to see if it still works when compiling...
<gjanssens>yes, it works fine in compiled mode as well
<mark_weaver>sweet!
<gjanssens>thanks very much again for your support
<mark_weaver>no problem! thanks for working on this :)
<gjanssens>it even works without the expand keyword added in eval-when
<mark_weaver>it's a great relief to have one less major project stuck on 1.8
<wingo>a report for gnucash was the first thing i ever programmed in scheme
<wingo>so nice to have us all on 2.0 :)
<mark_weaver>well, there's still texmacs and lilypond :)
<gjanssens>is there are reason to keep it ?
<gjanssens>:)
<gjanssens>gnucash is not fully 1.8 free :(
<gjanssens>our windows and mac ports are still on 1.8
<mark_weaver>well, it sounds like it's well on its way.
<gjanssens>but at least it runs under guile 2
<gjanssens>(and getting the windows build working on guile 2 will probably another job for yours truly)
<gjanssens>but that will have to wait until after the 2.6 release that's pending
<mark_weaver>1.8 hasn't been supported for a long time, and has quite a few known but unfixed bugs.
*gjanssens will hurry up then ;)
<mark_weaver>:)
<gjanssens>any comment on the expand being optional ?
<mark_weaver>wingo: in (eval-when (compile load eval) (use-modules (ice-9 local-eval))), should 'expand' be in there as well to cover the non-compiled case, or is that redundant?
<mark_weaver>(this is within a 'cond-expand')
*wingo thinks
<gjanssens>it did work in the non-compiled case without expand
<gjanssens>just want to be sure that wasn't pure luck
<mark_weaver>for that matter, I'm not even sure why the 'eval-when' is needed at all, given that this is at top-level. (well, it's within 'cond-expand', but I thought that's still essentially top-level)
<wingo>eval-when usually twists my brain...
<lloda>let's rename it to evil-always
<wingo>heh heh expand isn't even documented, sadness
<wingo>i don't recall the situations that prompted the addition of expand
<wingo>almost assuredly (compile load eval) is fine, but it would take some research to understand more about expand
<mark_weaver>which of those keywords ensures that it's loaded during macro expansion outside of the compiler?
<mark_weaver>personally, I would first try removing the 'eval-when' altogether, and see if that works. if so, great. otherwise, I'd add the 'expand' to be safe.
<mark_weaver>(without the 'expand', it might be working simply because (ice-9 local-eval) has already been loaded)
<wingo>ok so expand is a synonym of compile if macroexpand is invoked with a mode of 'c or 'c&e (respectively: compile or compile-and-eval; horrible.)
<wingo>otherwise if mode is 'e (for just eval) then... hoo complicated
*mark_weaver thinks the 'eval-when' is not even needed here.
*gjanssens just tried without eval-when
<gjanssens>that work as well indeed
<wingo>then if in mode 'e, eval is not present in the eval-when situations, then expand causes the expression to still be evaluated, whereas otherwise it would not be
<wingo>if eval is present, then i don't fully understand it
<mark_weaver>'use-modules' is a macro that expands to something that includes (eval-when (eval load compile expand) (process-use-modules ...))
<wingo>macrology: is it good or is it wack
<wingo> http://www.youtube.com/watch?v=T9CEqlUJGCE
<mark_weaver>gjanssens: I'd just leave out the 'eval-when', then.
<mark_weaver>but for the record, I think that if it were there, 'expand' would be needed for correctness.
<mark_weaver>my understanding of the keywords is as follows: 'compile' is only when the module is compiled. more generally, 'expand' is when it's macro expanded in all cases (including non-compilation). 'load' is when the (possibly pre-compiled) module is loaded into guile. and 'eval' is the obvious last step.
<wingo>sounds plausible, i hope it is true
<mark_weaver>gjanssens: did you remove it from both taxinvoice.scm and eguile-gnc.scm ?
<gjanssens>yes
<mark_weaver>sounds good
<gjanssens>mark_weaver: you may want to add another documentation update to your TODO list :)
<gjanssens>the documentation on eval-when only talks of three keywords and voids waranty if used otherwise :)
<mark_weaver>done :)
<mark_weaver>(added to my TODO list, that is)
<mark_weaver>'expand' should definitely be there. it is often needed.
<gjanssens>but if I understand well whenever cond-expand is used to conditionally invoke use-modules, eval-when is not needed
<mark_weaver>right
<gjanssens>because that's actually handled by the use-modules macro itself
<mark_weaver>more generally, I don't see why 'use-modules' should ever need to be wrapped in 'eval-when'.
<mark_weaver>yes, exactly.
<wingo>so, question. floating-point arithmetic is not associative. is floating point arithmetic *in scheme* associative?
<wingo>given that they are marked as inexact
*wingo ignorant
<wingo>good evening jao
<mark_weaver>wingo: no
<mark_weaver>the reason has to do with round-off errors.
<wingo>so i know that is the case in general, or at least i understand it to be the case
<wingo>but i wondered if scheme's magical "it's inexact" pixie dust gives us any leeway
<mark_weaver>well written inexact math code has to be very careful about the order in which operations are done, in order to prevent things like catastrophic loss of precision in some cases.
<mark_weaver>if a compiler changes things according to the rules of exact arithmetic, it can mess that all up.
<wingo>i heard g. sussman say at one point that floating point is one of the most terrifying things for him ;)
<mark_weaver>I'm afraid that unless you know the values are exact, there's not much you can safely do with arithmetic code in terms of optimizations.
<wingo>that's a bummer
<mark_weaver>yes, it is :-(
<lloda>i used to think, programming in C, that the compiler could do a+b+c in whatever order it pleased, but that if I wrote a+(b+c), it would respect that.
<lloda>see http://gcc.gnu.org/ml/gcc/2004-03/msg01425.html (just first search)
<lloda>it says this is what Fortran does, it that's what seems more reasonable to me
<lloda>*if* your code depends on evaluation order, this order should be explicit in some way (like writing (a+b)+c instead of a+b+c).
<lloda>otherwise, let the compiler do its thing
<mark_weaver>looking at R6RS, I see that the docs don't specify the order in which arguments to '+' or '*' are combined.
<mark_weaver>so, I think we could say that (+ a b c) could do either (+ (+ a b) c) or (+ a (+ b c))
<mark_weaver>however, if the user writes (+ (+ a b) c) or (+ a (+ b c)), and we cannot prove that the numbers are all exact, then we must honor the specified order of operations. otherwise it will be impossible to write robust numeric code.
<lloda>yes & yes
<lloda>it's good if there's a way to say 'do it this way' and a way to say 'do it however you prefer'
<mark_weaver>for '-' and '/', the R6RS specifies left-associativity, so we cannot mess with those.
<mark_weaver>in particular, we cannot change (- a b c) to (- a (+ b c))
<mark_weaver>(actually, right now, all released versions of guile get this wrong. I fixed it in http://git.savannah.gnu.org/gitweb/?p=guile.git;a=commit;h=71673fba930d735c09184d5ca115882239edabb3, which will be in stable-2.0)
<mark_weaver>which will be in 2.0.10, I mean.
<wingo>nice
<mark_weaver>well, all released versions of guile 2.0.x get it wrong, anyway. I'm not sure about 1.8
<kurohin>/
<kurohin>Is there any good examples somewhere on how to use libguile as configuration language for an application?
<kurohin>join #emacs