Re: Improve `seed->random-state' in stable-2.0?
David Kastrup writes: > Actually, you don't need a PRNG at all. Generate a _good_ random > starting value, and count sequentially from there. This is _exactly_ what my patch does, on a per-thread basis. The starting value is read directly from /dev/urandom if available. However, if /dev/urandom cannot be read, the PRNG is used to generate the starting value. This is a last resort, and ideally we should never use it. Thanks, Mark
Re: Eval, tail calls, (current-module), and backward compatibility
Mark H Weaver writes: > Ideally, I think that `eval' should set (current-module) during > expansion, but _not_ during evaluation. Then it can be properly tail > recursive. However, some code out there might depend on the existing > behavior, so I guess we can't change this, at least not in 2.0. > Bummer. It just occured to me that the _only_ way of getting and setting variables under a computed name (apart from using macros) is using (module-set! (current-module) (compute a symbol)) since symbol-set! apparently has been deprecated. Not sure what the implications of that are. -- David Kastrup
Re: Eval, tail calls, (current-module), and backward compatibility
David Kastrup writes: > Mark H Weaver writes: > >> Ideally, I think that `eval' should set (current-module) during >> expansion, but _not_ during evaluation. Then it can be properly tail >> recursive. However, some code out there might depend on the existing >> behavior, so I guess we can't change this, at least not in 2.0. >> Bummer. > > It just occured to me that the _only_ way of getting and setting > variables under a computed name (apart from using macros) is using > (module-set! (current-module) (compute a symbol)) > since symbol-set! apparently has been deprecated. If you want to get or set a top-level variable with a computed name, then you need to know which module to use. Otherwise, how could Guile possibly know which module you intended? Remember, (current-module) is a compile-time concept, not a run-time concept. It is probably not the right choice except in something like a REPL, and only if you specifically want the same module that's being used to compile new top-level forms (using `primitive-eval'). It's unfortunate, but just as support for multiple string encodings forces us now to think clearly about which encoding to use for a given bytevector in our code (and there's really no way around this), the same is also true of modules. For non-computed variable references, there is a robust automatic answer: use the module that was baked into the source identifier before macro expansion. However, this cannot be done for computed variable names. Thanks, Mark
Re: Eval, tail calls, (current-module), and backward compatibility
Mark H Weaver writes: > Remember, (current-module) is a compile-time concept, not a run-time > concept. Then current-module should probably be a macro, not a function. In which case the tail call problem would take care of itself. -- David Kastrup
Re: Eval, tail calls, (current-module), and backward compatibility
David Kastrup writes: > Mark H Weaver writes: > >> Remember, (current-module) is a compile-time concept, not a run-time >> concept. I should clarify this statement. (current-module) is used by the code that's doing the compiling (e.g. the REPL), _not_ by the code that's being compiled. It is a run-time variable used by REPLs and compilers to keep track of which module should be used to compile the next form. > Then current-module should probably be a macro, not a function. In > which case the tail call problem would take care of itself. A core syntax form to retrieve the module name baked into a given identifier (a constant) would probably be useful, and indeed I suspect we'll have it in 2.0.4 because it'll be needed for Andy's implementation of `local-eval'. However, that's a different concept from (current-module), therefore it would need a different name. To understand (current-module), please read my first post in this thread. It would make no sense as a macro. Mark
Re: guile 1.8.3 fails to build on sparc
l...@gnu.org (Ludovic Courtès) writes: > l...@gnu.org (Ludovic Courtès) writes: > >> Rob: Would it be possible for you to try out this patch on one of the >> Debian SPARC machines? > > And here's the patch. ;-) It looks like that doesn't fix the problem -- it failed on ia64 this time: https://buildd.debian.org/status/fetch.php?pkg=guile-1.8&arch=ia64&ver=1.8.8%2B1-7&stamp=1323288478 The bug also appears to affect Guile 2.0 on kfreebsd-i386, s390, and perhaps others (some archs won't build 2.0 at all yet) see the "last log" links here: https://buildd.debian.org/status/package.php?p=guile-2.0&suite=sid i.e., for the gc.test problem on kfreebsd-i386 and s390: https://buildd.debian.org/status/fetch.php?pkg=guile-2.0&arch=kfreebsd-i386&ver=2.0.3%2B1-2&stamp=1322025585 https://buildd.debian.org/status/fetch.php?pkg=guile-2.0&arch=s390&ver=2.0.3%2B1-2&stamp=1322025002 Anything else I might try? Thanks -- Rob Browning rlb @defaultvalue.org and @debian.org GPG as of 2002-11-03 14DD 432F AE39 534D B592 F9A0 25C8 D377 8C7E 73A4
Re: add-relative-load-path ?
Andy Wingo writes: > Hi Neil, > > On Sat 14 Jan 2012 22:48, Neil Jerram writes: > >> Andy Wingo writes: >> >> Of the possibilities above, I think I prefer >> >>> (add-to-load-path (dirname (current-source-filename))) > > Done. Actually I called it "current-filename", so it would be: > > (add-to-load-path (dirname (current-filename))) > > Feedback is very welcome -- especially timely feedback; it would be nice > to release on Monday or so. I'm attaching the patch (already committed) > to make it easy for you :) Thanks! The patch works for me, although there are a couple of points that still make it a bit fiddly to use in practice. It might be possible to improve the first of those points, but I don't think anything can be done about the second. Thing 1 is that (current-filename) can return a relative filename, or a filename with a "./" in its middle: 1.1: With a script called "affiche", with "#! /usr/bin/guile -s" and which I invoke from the shell as "./affiche", (current-filename) gives "/home/neil/q/SW/ossaulib/scripts/./affiche". So if I do (dirname (dirname (current-filename)), intending to get the parent directory "/home/neil/q/SW/ossaulib", I actually get "/home/neil/q/SW/ossaulib/scripts". 1.2: If I encapsulate the load-path logic in a separate file called "setup-load-path.scm", and take advantage of the fact that (include "setup-load-path.scm") will find that file in the same directory as "affiche", (current-filename) gives just "setup-load-path.scm", and (dirname ...) on that won't give a useful result. Both problems are solved by adding in a canonicalize-path call. Would there be any downside from putting that inside current-filename, so that current-filename always returns a canonical file name? Alternatively, I think the use of canonicalize-path should be added into the example in the manual. Thing 2 is that it remains slightly inelegant to cater for both 1.8 and 2.0. I think the minimal complete solution is to write (cond-expand (guile-2 (include "setup-load-path.scm")) (else (load "setup-load-path.scm"))) at top level in every uninstalled script, and then something like (cond-expand (guile-2 (add-to-load-path (dirname (dirname (canonicalize-path (current-filename)) (else ;; Less elegant code for 1.8... (let* ((bindir (dirname (car (command-line (absdir (cond ((string=? bindir ".") (getcwd)) ((string-match "^/" bindir) bindir) (else (in-vicinity (getcwd) bindir) (set! %load-path (cons (in-vicinity absdir "..") %load-path) in setup-load-path.scm. But without a time machine I don't think anything can be done to make either of those fragments more concise. I also had just one comment on the doc: > @@ -814,9 +780,9 @@ change occurs at the right time. > @defvar %load-hook > A procedure to be called @code{(%load-hook @var{filename})} whenever a > file is loaded, or @code{#f} for no such call. @code{%load-hook} is > -used by all of the above loading functions (@code{load}, > -@code{load-path}, @code{primitive-load} and > -@code{primitive-load-path}). > +used by all of the loading functions (@code{load} and > +@code{primitive-load}, and @code{load-path} and > +@code{primitive-load-path} documented in the next section). [...] > +@deffn {Scheme Procedure} load-from-path filename Is it 'load-path' or 'load-from-path'? Regards, Neil
Fun (system foreign) / D-Bus / oFono hacking
Just in case anyone else is interested in these areas... I had a really fun time today using the dynamic FFI to hack up Guile code to access oFono's D-Bus API. It's really great to be able to do this, even if it might be more efficient in the long run to write a proper C binding. I've attached the extremely-thrown-together code below. Obviously it ought to evolve (at least) into a more generic D-Bus module, and an oFono-specific module that uses that, but right now I'm just playing... Neil (use-modules (system foreign) (rnrs bytevectors)) (define gobject (dynamic-link "libgobject-2.0")) (define glib (dynamic-link "libglib-2.0")) (define gio (dynamic-link "libgio-2.0")) (write gobject) (newline) (write glib) (newline) (write gio) (newline) (dynamic-call "g_type_init" gobject) (define FALSE 0) (define TRUE 1) (define g_main_loop_new (pointer->procedure '* (dynamic-func "g_main_loop_new" glib) (list '* int))) (define loop (g_main_loop_new %null-pointer FALSE)) (write loop) (newline) (define g_dbus_proxy_new_for_bus_sync (pointer->procedure '* (dynamic-func "g_dbus_proxy_new_for_bus_sync" gio) (list int ; bus type int ; flags '* ; interface info '* ; bus name '* ; object path '* ; interface name '* ; cancellable '* ; error ))) ;; bus type (define G_BUS_TYPE_SYSTEM 1) (define G_BUS_TYPE_SESSION 2) ;; flags (define G_DBUS_PROXY_FLAGS_NONE 0) (define manager-proxy (g_dbus_proxy_new_for_bus_sync G_BUS_TYPE_SYSTEM G_DBUS_PROXY_FLAGS_NONE %null-pointer (string->pointer "org.ofono") (string->pointer "/") (string->pointer "org.ofono.Manager") %null-pointer %null-pointer)) (write manager-proxy) (newline) (define g_dbus_proxy_call_sync (pointer->procedure '* (dynamic-func "g_dbus_proxy_call_sync" gio) (list '* ; proxy '* ; method_name '* ; parameters int ; flags int ; timeout_msec '* ; cancellable '* ; error ))) (define return-parms (g_dbus_proxy_call_sync manager-proxy (string->pointer "GetModems") %null-pointer 0 1000 %null-pointer %null-pointer)) (define g_variant_get_child_value (pointer->procedure '* (dynamic-func "g_variant_get_child_value" glib) (list '* ; variant int ; index ))) (define g_variant_print (pointer->procedure '* (dynamic-func "g_variant_print" glib) (list '* ; variant int ; type annotate ))) (define g_variant_get_type (pointer->procedure '* (dynamic-func "g_variant_get_type" glib) (list '* ; variant ))) (define g_variant_get_string (pointer->procedure '* (dynamic-func "g_variant_get_string" glib) (list '* ; variant '* ; length ))) (define (print-variant variant) (if (null-pointer? variant) (display "(null variant pointer)") (begin (display (pointer->string (g_variant_get_type variant))) (display ": ") (display (pointer->string (g_variant_print variant FALSE) (newline)) (print-variant return-parms) (define modems (g_variant_get_child_value return-parms 0)) (print-variant modems) (define first-modem (g_variant_get_child_value modems 0)) (print-variant first-modem) (define modem-name (g_variant_get_child_value first-modem 0)) (print-variant modem-name) (define modem-name-string (pointer->string (g_variant_get_string modem-name %null-pointer))) (format #t "First modem's name is ~a\n" modem-name-string) (define modem-proxy (g_dbus_proxy_new_for_bus_sync G_BUS_TYPE_SYSTEM
Re: syntax-local-binding
Hi, Mark H Weaver skribis: > Because it breaks your nice equivalence. For example: > > (let ((x 1)) > (syntax-local-binding #'x)) > > is not equivalent to: > > (let ((x 1)) > (local-eval '(syntax-local-binding #'x) (the-environment))) > > Put another way: if anyone uses `syntax-local-binding' to distinguish > lexical variables from macros in some clever macro of theirs, this means > that `local-eval' is now buggy with regard to their clever macro. What about recommending against “clever macros” that use ‘syntax-local-binding’, or documenting the limitation in how ‘local-eval’ and ‘syntax-local-binding’ would interact? After all, the point of ‘local-eval’ is to provide a compatibility later with 1.8, and ‘syntax-local-binding’ didn’t exist there. Thanks, Ludo’.
Re: impressions on gc
Hi Noah, Noah Lavine skribis: > As long as we're pinging people for 2.0.5, I don't think this patch > ever got pushed. :-) Apparently it was applied as 4eb286127c41e67eb90ef1b69f61f613bcd830b2. Thanks, Ludo’.
Re: syntax-locally-bound-identifiers, local-eval
Andy Wingo skribis: > (define-syntax lexicals > (lambda (x) > (syntax-case x () > ((lexicals) #'(lexicals lexicals)) > ((lexicals scope) > (with-syntax (((id ...) > (filter (lambda (x) > (eq? (syntax-local-binding x) > 'lexical)) > (syntax-locally-bound-identifiers > #'scope > #'(list (cons 'id id) ...)) > > (let* ((x 10) (x 20)) (lexicals)) > => ((x . 10) (x . 20)) Ooooh, I’m starting to find it fun! :-) Ludo’.
Re: Fun (system foreign) / D-Bus / oFono hacking
Hi Neil! It looks like fun, and it’s great that the FFI allows for quick & fruitful experiments like this. Thanks, Ludo’.
Re: syntax-locally-bound-identifiers, local-eval
Hi Andy, > There's another thing that really should be fixed, for the sake of > preserving our ability to change the implementation `local-eval' in the > future. > > Since (the-environment) can be included in code compiled to disk, the > lexical environment objects that it returns are effectively now part of > our ABI. As it is now, if we want to change the representation, we'll > be in for a lot of headaches to support lexical environments produced by > older code. > > The fix is simple: Simply change the representation of the lexical > environment object to contain only a single field: a procedure that > takes an expression (and optional keyword arguments) and does the > equivalent of `local-eval' or `local-compile'. (The keyword arguments > should specify whether or not to compile, and the compile options). > > Then, `local-eval' and `local-compile', when applied to a lexical > environment object, should simply call the embedded procedure. To help facilitate this change, I've attached a small patch to change my variant of `local-eval' to use this simple future-proof representation. As you can see, the changes are simple and nicely localized. I'll leave it to you to adapt these changes to your implementation. Also, see below for an improved "the-environment within a macro" test that now checks that the proper module was stored in the lexical environment. Please verify that this works properly with your patch. Thanks! Mark (pass-if "the-environment within a macro" (let ((module-a-name '(test module the-environment a)) (module-b-name '(test module the-environment b))) (let ((module-a (resolve-module module-a-name)) (module-b (resolve-module module-b-name))) (module-use! module-a (resolve-interface '(guile))) (module-use! module-a (resolve-interface '(ice-9 local-eval))) (eval '(begin (define z 3) (define-syntax-rule (test) (let ((x 1) (y 2)) (the-environment module-a) (module-use! module-b (resolve-interface '(guile))) (let ((env (eval `(let ((x 111) (y 222)) ((@@ ,module-a-name test))) module-b))) (equal? (local-eval '(list x y z) env) '(1 2 3)) diff --git a/module/ice-9/local-eval.scm b/module/ice-9/local-eval.scm index ece1313..fb6752c 100644 --- a/module/ice-9/local-eval.scm +++ b/module/ice-9/local-eval.scm @@ -24,34 +24,20 @@ #:export (local-eval local-compile)) (define-record-type lexical-environment-type - (make-lexical-environment module wrapper boxes pattern-bindings -var-names pattern-var-names unsupported-names) + (make-lexical-environment version evaluator) lexical-environment? - (modulelexenv-module) - (wrapper lexenv-wrapper) - (boxes lexenv-boxes) - (pattern-bindings lexenv-pattern-bindings) - (var-names lexenv-var-names) - (pattern-var-names lexenv-pattern-var-names) - (unsupported-names lexenv-unsupported-names)) + (version lexenv-version) + (evaluator lexenv-evaluator)) (set-record-type-printer! lexical-environment-type (lambda (e port) - (format port "#" - (module-name (lexenv-module e)) - (reverse (map (lambda (name box) (list name (box))) - (lexenv-var-names e) (lexenv-boxes e))) - (reverse (lexenv-pattern-var-names e)) - (reverse (lexenv-unsupported-names e) + (format port "#"))) (define (local-eval x e) "Evaluate the expression @var{x} within the lexical environment @var{e}." (cond ((lexical-environment? e) - (apply (eval ((lexenv-wrapper e) x) - (lexenv-module e)) -(append (lexenv-boxes e) -(lexenv-pattern-bindings e + ((lexenv-evaluator e) x #f)) ((module? e) ;; Here we evaluate the expression within `lambda', and then ;; call the resulting procedure outside of the dynamic extent @@ -64,11 +50,7 @@ (define* (local-compile x e #:key (opts '())) "Compile and evaluate the expression @var{x} within the lexical environment @var{e}." (cond ((lexical-environment? e) - (apply (compile ((lexenv-wrapper e) x) - #:env (lexenv-module e) - #:from 'scheme #:opts opts) -(append (lexenv-boxes e) -(lexenv-pattern-bindings e + ((lexenv-evaluator e) x opts)) ((module? e) ;; Here we compile the expression within `lambda', and then ;; call the resulting procedure outside of the dynamic extent @@ -109,18 +91,21 @@ (((nested-pvar ...) (map within-nested-ellipses #'(pvar ...) #'(pvar-lvl ... #'(make-lexical-environment -module -(