Re: Fwd: new function
i have tested define-once http://www.gnu.org/software/guile/docs/master/guile.html/Top-Level.html (the defvar of Lisp)and idea are: -unfortunately it is considered by scheme as a define,so there is some context where it is not allowed in my code -seems to work fine at toplevel (as mentioned in doc) but strange behavior in a function, i did not understand really what happened but i got some #unspecified value. here are my test code: cheme@(guile-user)> (define (foo2) (define-once x 1) (if #t (let () (define-once x 2) ;;(set! x 2) (display "x=") (display x) (newline)) 'never) (display x) (newline)) scheme@(guile-user)> x ;;; : warning: possibly unbound variable `x' ice-9/boot-9.scm:1669:16: In procedure raise-exception: Unbound variable: x Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. scheme@(guile-user) [1]> ,q scheme@(guile-user)> (foo2) x=2 1 scheme@(guile-user)> (foo2) x=2 1 scheme@(guile-user)> x ;;; : warning: possibly unbound variable `x' ice-9/boot-9.scm:1669:16: In procedure raise-exception: Unbound variable: x Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. scheme@(guile-user) [1]> ,q scheme@(guile-user)> (define x 3) scheme@(guile-user)> (foo2) x=# # scheme@(guile-user)> x 3 it does not seem to help me, perheaps if i can test the return of # Damien On Sun, Sep 19, 2021 at 4:46 PM Matt Wette wrote: > > > On 9/19/21 3:38 AM, Maxime Devos wrote: > > Damien Mattei schreef op zo 19-09-2021 om 11:18 [+0200]: > >> -- Forwarded message - > >> From: Damien Mattei > >> Date: Sun, Sep 19, 2021 at 9:54 AM > >> Subject: new function > >> To: > >> > >> > >> hello, > >> i'm developing an extension to Scheme > >> and i need a procedure or macro that define a variable only if it is not > >> bind and if it is just set! it. > > Could you give an example in which the hypothetical define-or-set! is > used? > > I wonder where such a thing would be useful. > > > >> I can not do it in Guile or any Scheme,and i'm desperately searching a > way > >> to do that. I finally conclude that it can be done only by adding it in > the > >> language. > >> > >> Can someone include a such function in Guile next release? > >> i know guile have a predicate defined? > > defined? only works on global variables, not on lexicals, > > and depends on the (current-module), which is not necessarily > > the module defined? is used in. > > > >> to test binfing of a vairable but > >> writing a macro with it is not possible because define can be used in an > >> expression context. > > You can use 'syntax-local-binding'. > > > > (use-modules (system syntax)) > > (define-syntax define-or-set! > >(lambda (s) > > (syntax-case s () > >((_ var value) > > (case (syntax-local-binding #'var) > > ((lexical displaced-lexical) #'(set! var value)) > > ((global) #'(define var value)) > > (else ???)) > > > > ,expand (define-or-set! a 0) ; $_ = (define a 0) > > ,expand (let ((a 0)) (define-or-set! a 0) a) ; $_ = (let ((a 0)) (set! a > 0) a) > > (define-or-set! a 0) > > ,expand (define-or-set! a 0) ; $_ = (define a 0) (might or might not be > acceptable for your use case > > ,expand (let () (define-or-set! a 0) (define-or-set! a 1) a) ; $_ = (let > () (define a 0) (set! a 1)) > > > > Greetings, > > Maxime. > > Does this work for you? > > scheme@(guile-user)> (define a 1) > scheme@(guile-user)> (define a 2) > scheme@(guile-user)> a > $2 = 2 > scheme@(guile-user)> > > > > > > >
Re: foreign objects and the garbage collector
Hi Olivier, thank you very much for your reply Il giorno dom, 19/09/2021 alle 14.11 -0400, Olivier Dion ha scritto: > On Sun, 19 Sep 2021, adriano wrote: > > > > > > It'd be so nice to have an example > > (define (with-my-resource token proc) > (let ((resource #f)) > (dynamic-wind > (lambda () > (set! resource (open-my-resource% token))) > > (proc resource) > > (lambda () > (when resource > (close-my-resource% resource)) > > (with-my-resource "some-internal-token" (lambda ())) Oh my, thank you for this ! This should be included in the manual ! The example that's there currently is totally indequate, in my opinion > > > > Says you have `open_my_resource()` and `close_my_resource()` in C in > library "libfoo.so" where open_my_resource takes a C string and returns > an integer for the resource while close_my_resource takes the integer > of > the resource: > > (define open-my-resource% > (eval-when (eval load compile) > (let ((this-lib (load-foreign-library "libfoo"))) > (foreign-library-function this-lib "open_my_resource" > #:return-type int > #:arg-types (list '* > > (define open-my-resource% > (eval-when (eval load compile) > (let ((this-lib (load-foreign-library "libfoo"))) > (foreign-library-function this-lib "open_my_resource" > #:return-type int > #:arg-types (list int) Uhmm... I see 2 versions of open-my-resource% The only slight difference I see is in the #:arg-types The first one has (list '*) and the second one has (list int) Maybe you you got confused while editing ? This would be my version of close-my-resource% (define close-my-resource% (eval-when (eval load compile) (let ((this-lib (load-foreign-library "libfoo"))) (foreign-library-function this-lib "close_my_resource" #:return-type int #:arg-types (int) > > Note that you probably need to do a wrapper named `open-my-resource` > to > do the conversion of scm_string to C raw pointer before calling > `open-my-resource%` in this particular case. Ok > > This is just an example, but it shows you that you can call foreign C > primitives easily without any C code, and that you have to use a > dynamic context to manage the lifetime of the C resources. > Thank you again
Re: foreign objects and the garbage collector
On Tue, 21 Sep 2021, adriano wrote: > Hi Olivier, > > thank you very much for your reply > > Il giorno dom, 19/09/2021 alle 14.11 -0400, Olivier Dion ha scritto: >> On Sun, 19 Sep 2021, adriano wrote: >> > >> > > > > > >> > It'd be so nice to have an example >> >> (define (with-my-resource token proc) >> (let ((resource #f)) >> (dynamic-wind >> (lambda () >> (set! resource (open-my-resource% token))) >> >> (proc resource) >> >> (lambda () >> (when resource >> (close-my-resource% resource)) >> >> (with-my-resource "some-internal-token" (lambda ())) > > Oh my, thank you for this ! > > This should be included in the manual ! > > The example that's there currently is totally indequate, in my opinion > >> > >> >> Says you have `open_my_resource()` and `close_my_resource()` in C in >> library "libfoo.so" where open_my_resource takes a C string and returns >> an integer for the resource while close_my_resource takes the integer >> of >> the resource: >> >> (define open-my-resource% >> (eval-when (eval load compile) >> (let ((this-lib (load-foreign-library "libfoo"))) >> (foreign-library-function this-lib "open_my_resource" >> #:return-type int >> #:arg-types (list '* >> >> (define open-my-resource% >> (eval-when (eval load compile) >> (let ((this-lib (load-foreign-library "libfoo"))) >> (foreign-library-function this-lib "open_my_resource" >> #:return-type int >> #:arg-types (list int) > > Uhmm... I see 2 versions of open-my-resource% > The only slight difference I see is in the #:arg-types > > The first one has > > (list '*) > > and the second one has > > (list int) > > > Maybe you you got confused while editing ? You're right. I copy paste the form two times and forget to edit the second binding name. I meant `close-my-resource%` for the second define. > > Thank you again Just make sure to read what Maxime says about escape continuation. Dynamic wind are not bullet proof. As the manual says: If, any time during the execution of THUNK, the dynamic extent of the ‘dynamic-wind’ expression is escaped non-locally, OUT_GUARD is called. If the dynamic extent of the dynamic-wind is re-entered, IN_GUARD is called. Thus IN_GUARD and OUT_GUARD may be called any number of times. Thus, you could also do a `(set! resource #f)` after freeing it, so that the overall dynamic-wind is reentrant and you don't end up with double free of resource. -- Olivier Dion Polymtl
Re: foreign objects and the garbage collector
Hi Maxime, Il giorno dom, 19/09/2021 alle 20.23 +0200, Maxime Devos ha scritto: > Olivier Dion via General Guile related discussions schreef op zo 19- > 09-2021 om 14:11 [-0400]: > > On Sun, 19 Sep 2021, adriano wrote: > > > > If you want to avoid the problem, you should explicitely bind > > > > and > > > > call the gps-close function and not rely on the garbage > > > > collector to > > > > do it for you. You can use dynamic-wind to open and close > > > > resources as needed. > > > > > > It'd be so nice to have an example > > > > (define (with-my-resource token proc) > > (let ((resource #f)) > > (dynamic-wind > > (lambda () > > (set! resource (open-my-resource% token))) > > > > (proc resource) > > > > (lambda () > > (when resource > > (close-my-resource% resource)) > > > > (with-my-resource "some-internal-token" (lambda ())) > > FWIW, this doesn't work well with continuations, e.g. if you use > guile-fibers > for concurrency. I'm not familiar with 'libgps', so I'm not sure if > it would > work for you, but another method for implementing with-my-resource > could be to > use the exception handling mechanism to call 'close-my-resource' on > both > normal exits and abnormal exits. > > Note that this alternative method does _not_ close the resource when > calling > an escape continuation (let/ec (with-my-resource .. (lambda (r) (ec) > (unreachable, > so you might want to use something like guardians and after-gc-hook > to eventually > free the resource. > > (Here, close-my-resource is like close-my-resource% except it doesn't > do anything > if the resource is already closed.) > > Greetings, > Maxime. Well, it'd be wonderful to have an example of what you're describing here ! 🙂️ The new exceptions system is still quite obscure 🤷️
Re: foreign objects and the garbage collector
Il giorno mar, 21/09/2021 alle 10.25 -0400, Olivier Dion ha scritto: > On Tue, 21 Sep 2021, adriano wrote: > > Hi Olivier, > > > > thank you very much for your reply > > > > Il giorno dom, 19/09/2021 alle 14.11 -0400, Olivier Dion ha > > scritto: > > > On Sun, 19 Sep 2021, adriano wrote: > > > > > > > > > > > > > > > > > > > > It'd be so nice to have an example > > > > > > (define (with-my-resource token proc) > > > (let ((resource #f)) > > > (dynamic-wind > > > (lambda () > > > (set! resource (open-my-resource% token))) > > > > > > (proc resource) > > > > > > (lambda () > > > (when resource > > > (close-my-resource% resource)) > > > > > > (with-my-resource "some-internal-token" (lambda ())) > > > > Oh my, thank you for this ! > > > > This should be included in the manual ! > > > > The example that's there currently is totally indequate, in my > > opinion > > > > > > > > > > > > Says you have `open_my_resource()` and `close_my_resource()` in C > > > in > > > library "libfoo.so" where open_my_resource takes a C string and > > > returns > > > an integer for the resource while close_my_resource takes the > > > integer > > > of > > > the resource: > > > > > > (define open-my-resource% > > > (eval-when (eval load compile) > > > (let ((this-lib (load-foreign-library "libfoo"))) > > > (foreign-library-function this-lib "open_my_resource" > > > #:return-type int > > > #:arg-types (list '* > > > > > > (define open-my-resource% > > > (eval-when (eval load compile) > > > (let ((this-lib (load-foreign-library "libfoo"))) > > > (foreign-library-function this-lib "open_my_resource" > > > #:return-type int > > > #:arg-types (list int) > > > > Uhmm... I see 2 versions of open-my-resource% > > The only slight difference I see is in the #:arg-types > > > > The first one has > > > > (list '*) > > > > and the second one has > > > > (list int) > > > > > > Maybe you you got confused while editing ? > > You're right. I copy paste the form two times and forget to edit the > second > binding name. I meant `close-my-resource%` for the second define. > > > > > Thank you again > > Just make sure to read what Maxime says about escape continuation. > Dynamic wind are not bullet proof. > > As the manual says: > > If, any time during the execution of THUNK, the dynamic > extent of > the ‘dynamic-wind’ expression is escaped non-locally, > OUT_GUARD is > called. If the dynamic extent of the dynamic-wind is re- > entered, > IN_GUARD is called. Thus IN_GUARD and OUT_GUARD may be > called any > number of times. > > Thus, you could also do a `(set! resource #f)` after freeing it, so > that > the overall dynamic-wind is reentrant and you don't end up with > double > free of resource. > After seeing your example of usage of dinamic-wind, I understand what IN_GUARD and OUT_GUARD are supposed to be Before that it was quite nebulous Thanks again
Re: foreign objects and the garbage collector
adriano schreef op di 21-09-2021 om 16:26 [+0200]: > > [...] > Well, it'd be wonderful to have an example of what you're describing > here ! 🙂️ > > The new exceptions system is still quite obscure 🤷️ Ignoring with-throw-handler, raise-continuable and pre-unwind handlers, it's the same mechanism as in Java or Python, though with different syntax, and unlike Java, Guile doesn't have ‘finally’: ;; Can also be implemented with the old 'catch' -- 'catch' isn't disappearing. (guard (c (#t (close-resource-unless-closed the-resource) (raise-exception c))) (define-values return-values (do-stuff)) (close-the-resource-unless-closed the-resource) (apply values return-vales)) Greetings, Maxime signature.asc Description: This is a digitally signed message part
Re: Fwd: new function
Damien Mattei schreef op di 21-09-2021 om 15:04 [+0200]: > i have tested define-once > http://www.gnu.org/software/guile/docs/master/guile.html/Top-Level.html > (the defvar of Lisp)and idea are: > -unfortunately it is considered by scheme as a define,so there is some > context where it is not allowed in my code > -seems to work fine at toplevel (as mentioned in doc) but strange behavior > in a function, i did not understand really what happened but i got some > #unspecified value. > > here are my test code: > cheme@(guile-user)> (define (foo2) > (define-once x 1) > (if #t > (let () > (define-once x 2) > ;;(set! x 2) > (display "x=") > (display x) > (newline)) > 'never) > (display x) > (newline)) Possibly you want (added a set? argument for demonstration): (define (foo2 set?) (define x) ; define an (undefined or unbound, not sure about terminology) variable (if set? (let () (set! x 2) ; change the value of x (display "x=") (display x) (newline)) 'never) (display x) (newline)) That should be portable and avoids global state. scheme@(guile-user)> x ;;; :20:0: warning: possibly unbound variable `x' ice-9/boot-9.scm:1685:16: In procedure raise-exception: Unbound variable: x scheme@(guile-user) [1]> ,q scheme@(guile-user) [1]> (foo2 #f) # ; I expected an error as would result from ... ;; ... this ... scheme@(guile-user)> (variable-ref (make-undefined-variable)) ice-9/boot-9.scm:1685:16: In procedure raise-exception: In procedure variable-ref: Unbound variable: #> Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. scheme@(guile-user) [2]> ;; instead of # but whatever ... scheme@(guile-user) [1]> (foo2 #t) x=2 2 scheme@(guile-user) [1]> (foo2 #t) x=2 2 scheme@(guile-user) [1]> (define x 3) scheme@(guile-user) [1]> (foo2 #t) x=2 ; foo2 doesn't use the global variable 'x' 2 scheme@(guile-user) [1]> x $1 = 3 Does this seem reasonable to you? signature.asc Description: This is a digitally signed message part