Re: Mixing syntax-rule and indentifier-syntax
On Tue 17 Jan 2012 00:11, Tobias Brandt writes: > I want to define a macro `with-vectors` that transforms this: > > (with-vectors (v) > (v 0) > (set! (v 0) 'foo) > (some-procedure v)) We currently don't have good support in the expander for variable transformers that take arguments. You can use a procedure-with-setter, perhaps. Another option would be to alias specific elements of your vector to identifiers: http://thread.gmane.org/gmane.lisp.guile.user/8724/focus=9100 Andy -- http://wingolog.org/
Re: Mixing syntax-rule and indentifier-syntax
Tobias Brandt writes: > Hi, > > is it possible to define a macro that does one thing when > it's in operator position and another when it's not? It depends what you mean by that. If you mean operator-position/set! position/ variable position, then that is id-syntax. If you mean something like (define-syntax foo (syntax-rules () [(bar foo baz) (baz bar)])) (9 foo sqrt) => (sqrt 9) then no. > I want to define a macro `with-vectors` that transforms this: > > (with-vectors (v) > (v 0) > (set! (v 0) 'foo) > (some-procedure v)) > > into this: > > (begin > (vector-ref v 0) > (vector-set! v 0 'foo) > (some-procedure v)) > > So far I have this: > > (define-syntax with-vectors > (syntax-rules () > ((_ (id ...) exp ...) > (let-syntax ((id* (syntax-rules () >((_ idx) (vector-ref id idx ...) > exp ... (define-syntax with-vectors (syntax-rules () ((_ (id ...) exp ...) (let-syntax ((id (make-variable-transformer (lambda (stx) (syntax-case stx () [(_ idx) #'(vector-ref id idx)] [idx #'id] ...) exp ... will cover scheme@(guile−user)> (with-vectors (k) (k 0)) $8 = 1 scheme@(guile−user)> (with-vectors (k) (vector-map (lambda (x) (* x x)) k)) $9 = #(1 4 9) but not the set!, which is slightly trickier. Since the second argument to set! must be (in an id-macro) an identifier, we need to do that conversion first, and AFAICS[0] that means turning the macro inside out, and walking it for set! forms. What I do is, walk the inner bodies for set! forms, if they are of the form (set! (foo bar) baz) where foo is a bound vector, I replace them with (set! foo (bar baz)). I later correct this in the identifier macro for foo. (define-syntax with-vectors (lambda (stx) (syntax-case stx () ((_ (id ...) exp ...) #`(with-vectors-helper (id ...) #,@(map (lambda (clause) (syntax-case clause (set!) ((set! (arg idx) val) ;; if arg is a bound vector (exists (lambda (x) (bound-identifier=? x #'arg)) #'(id ...)) ;; uses original set!, and package up ;; index and value, which we destructure ;; in the id-macro #'(set! arg (idx val))) (id #'id))) #'(exp ...))) (define-syntax with-vectors-helper (syntax-rules () ((_ (id ...) exp ...) (let-syntax ((id (make-variable-transformer (lambda (stx) (syntax-case stx (set!) [(_ idx) #'(vector-ref id idx)] [(set! id* (idx val)) ;; note, it is structured as above #'(vector-set! id idx val)] [idx #'id] ...) exp ... scheme@(guile−user)> (define k (vector 1 2 3)) scheme@(guile−user)> (with-vectors (k) (list (k 0) (k (k 1 $2 = (1 3) scheme@(guile−user)> (with-vectors (k) (list k (k 1))) $3 = (#(1 2 3) 2) scheme@(guile−user)> (with-vectors (k) (set! (k 0) #f) (list (k 0) k)) $4 = (#f #(#f 2 3)) scheme@(guile−user)> k $5 = #(#f 2 3) this set! modification only works at the first level of the with-vectors form, fixing that is left as an exercise :) 0. I'm sure there is another way, but my mind blanks at the moment -- Ian Price "Programming is like pinball. The reward for doing it well is the opportunity to do it again" - from "The Wizardy Compiled"
Re: Guile support in GNU make
Hi Paul, Paul Smith skribis: > On Sun, 2012-01-15 at 23:02 +0100, Ludovic Courts wrote: >> And thanks for the great news! :-) > > I promoted the feature to GNU make CVS (I know, still CVS!!) on > Savannah. I hope to generate a test dist file sometime this week. I'll > email when it's available if people want to take a look. Excellent! I just tried this: --8<---cut here---start->8--- $(guile (display "hello, world\n")) $(guile (pk (resolve-interface '(gnu make --8<---cut here---end--->8--- And then “make -f ./the-file.mk”. It works as intended ;-) but hits a segfault fixed with this patch: --- guile.c.~2.3.~ 2012-01-16 04:32:49.0 +0100 +++ guile.c 2012-01-17 23:35:53.0 +0100 @@ -92,9 +92,12 @@ func_guile (char *o, char **argv, const if (argv[0] && argv[0][0] != '\0') { char *str = scm_with_guile (internal_guile_eval, argv[0]); + if (str != NULL) + { o = variable_buffer_output (o, str, strlen (str)); free (str); } +} return o; } Anyway, nice job! :-) >> Paul Smith skribis: >> >> - The ‘#t => t’ distinguishes the symbol t from others, which feels wrong. >> >> I suggest #t => ""; #f => error. >> > >> > Hm. The problem with this is that we can't easily use Guile booleans in >> > GNU make. For example, the syntax for make's $(if ...) function is: >> > >> > $(if ,[,]) >> > >> > The is expanded as a makefile expression and if it's empty >> > it's considered false. If it's non-empty it's considered true. >> >> Would it be possible for Make to delay the conversion of SCMs to >> strings, and in turn to differentiate between conditions as strings, and >> conditions that are SCMs? > > I don't think this is possible. Make has no "data types" at all. It > just manipulates strings--every operation in make is a string operation, > and the "results" of operations are just constructing new string buffers > by doing string manipulations, then passing that string to the next > function (or whatever). > > There's just no facility anywhere internal to make to store or > manipulate a non-string item. OK, I see. > I suppose one option would be to have #f translate to the string "#f" > and change the definition in make of "false" to be "either the empty > string OR the string #f". Since "#" is a comment character in make it's > highly unlikely (although not impossible) someone would have that as a > valid value. It is possible to write valid GNU Make code that generates strings containing “#”? > However, this would be a lot of effort (finding all the places in make > that use the empty string as "false" and modifying them). And I'm not > sure it wouldn't cause other issues. I think, all in all, it's better > to leave it as-is unless someone can point out a real problem with it > (besides a general unpleasant aftertaste). Yeah. These are different “value worlds” (as Jim Blandy says), and one of them has a single data type, so this may be the best that can be done without introducing other data types in the Make language. Thanks! Ludo’.
Re: Guile support in GNU make
On Tue, 2012-01-17 at 23:42 +0100, Ludovic Courts wrote: > It works as intended ;-) but hits a segfault fixed with this patch: Doh! I added a feature to make that allows you to define functions separately (previously all functions had to be predefined in the static table in functions.c) and moved the guile function code out of function.c into guile.c for better encapsulation... And introduced a bug. Sigh. Thanks for the catch. > > I suppose one option would be to have #f translate to the string "#f" > > and change the definition in make of "false" to be "either the empty > > string OR the string #f". Since "#" is a comment character in make it's > > highly unlikely (although not impossible) someone would have that as a > > valid value. > > It is possible to write valid GNU Make code that generates strings > containing “#”? Yes; make supports escaping comment characters: ~$ cat > /tmp/x1.mk FOO = \# all: ; @echo 'FOO = $(FOO)' ~$ make -f /tmp/x1.mk FOO = # But my suspicion is that people would rarely use it due to annoyance factors. Thanks for testing this!
Re: Mixing syntax-rule and indentifier-syntax
> 0. I'm sure there is another way, but my mind blanks at the moment After you got me started, I was able to simplify and generalize it a bit. (-> is a GOOPS generic accessor I defined elsewhere. It works with vectors, arrays, strings, etc ...) (define-syntax with-accessors (lambda (stx) (syntax-case stx () ((_ (id ...) exp ...) #`(begin #,@(let (;; checks if arg is in the list of identifiers (id ...) (in-list? (lambda (arg) (exists (lambda (x) (bound-identifier=? x arg)) #'(id ...) ;; transform each expression in exp ... (map (lambda (clause) (syntax-case clause (set!) ;; setter ((set! (arg idx ...) val) (in-list? #'arg) #'((setter ->) arg idx ... val)) ;; getter ((arg idx ...) (in-list? #'arg) #'(-> arg idx ...)) (id #'id))) #'(exp ...
Re: Accessing multiple values from C
Hi Julian, thanks for working on this! Julian Graham writes: > +SCM > +scm_c_value_ref (SCM obj, size_t idx) > +{ > + SCM values = scm_struct_ref (obj, SCM_INUM0); > + return scm_list_ref (values, SCM_I_MAKINUM (idx)); > +} > + Should this verify that `obj' is a values object? Should it verify that `idx' can fit in an inum? Also, if `obj' is _not_ a values object and `idx' is 0, should this simply return `obj'? Since a single value is conceptually no different than multiple values (but is represented very differently within Guile), I'd think that this function should handle that case gracefully. What do other people think? Thanks, Mark