* macro like "my" in Perl @ 2002-06-25 22:19 Paul Jarc 2002-06-25 23:16 ` Robert Uhl <ruhl@4dv.net> ` (2 more replies) 0 siblings, 3 replies; 13+ messages in thread From: Paul Jarc @ 2002-06-25 22:19 UTC (permalink / raw) I'm looking for something like Perl's "my": something that adds a binding to the current environment (like internal defines), gives an error for multiple uses of the same symbol in a single scope (like internal defines and let), and lets previously-defined variables be used in values for later bindings (like let*). I expect I'll have to wrap the whole scope with a special macro, but I'd like to avoid having each definition wrap everything that comes after it. Is there anything like this already out there? (new-scope (my-define foo #t) (do-random-stuff-with foo) (my-define bar foo) (do-other-stuff-with bar)) paul _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-06-25 22:19 macro like "my" in Perl Paul Jarc @ 2002-06-25 23:16 ` Robert Uhl <ruhl@4dv.net> 2002-06-26 2:25 ` Alex Shinn 2002-07-12 20:43 ` Paul Jarc 2 siblings, 0 replies; 13+ messages in thread From: Robert Uhl <ruhl@4dv.net> @ 2002-06-25 23:16 UTC (permalink / raw) prj@po.cwru.edu (Paul Jarc) writes: > > I'm looking for something like Perl's "my": something that adds a > binding to the current environment (like internal defines), gives an > error for multiple uses of the same symbol in a single scope (like > internal defines and let), and lets previously-defined variables be > used in values for later bindings (like let*). I expect I'll have to > wrap the whole scope with a special macro, but I'd like to avoid > having each definition wrap everything that comes after it. Is there > anything like this already out there? Sounds like yet another job for bound?. Essentially, one could simply write a little macro which checks if something is bound, erroring if so, otherwise defining it and then doing something else. -- Robert Uhl <ruhl@4dv.net> The power of Satan is as nothing before the might of the Lord, so don't go getting any ideas. --I Abyssinians 20:20 _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-06-25 22:19 macro like "my" in Perl Paul Jarc 2002-06-25 23:16 ` Robert Uhl <ruhl@4dv.net> @ 2002-06-26 2:25 ` Alex Shinn 2002-06-26 13:15 ` Ken Anderson 2002-06-26 14:44 ` Lynn Winebarger 2002-07-12 20:43 ` Paul Jarc 2 siblings, 2 replies; 13+ messages in thread From: Alex Shinn @ 2002-06-26 2:25 UTC (permalink / raw) >>>>> "Paul" == Paul Jarc <prj@po.cwru.edu> writes: Paul> I'm looking for something like Perl's "my": [...] Paul> (new-scope Paul> (my-define foo #t) Paul> (do-random-stuff-with foo) Paul> (my-define bar foo) Paul> (do-other-stuff-with bar)) let* can do this if you want: (let* ((foo #t) (dummy (do-random-stuff-with foo)) (bar foo)) (do-other-stuff-with bar)) but that's rather poor style. If you just want bar to be some function of foo, you can do (let* ((foo #t) (bar (some-random-function-of foo))) (do-other-stuff-with bar)) or you can declare all the variables you need up front (let* ((foo #t) (bar #f)) (do-random-stuff-with foo) (set! bar foo) (do-other-stuff-with bar)) or nest let (let ((foo #t)) (do-random-stuff-with foo) (let ((bar foo)) (do-other-stuff-with bar))) I guess that's the real complaint... nested lets indent the code too much, but for some straight but very long procedural algorithms it's less clear to make all the variable decls up front when their use is localized. You can write new-scope as a low-level macro that walks the code, turning my-define into set! and accumulating all the variable names used into one top-level let. Something like (define-macro (new-scope . code) (let ((vars (map cadr (filter (lambda (x) (eq? (car x) 'my-define)) code)))) `(let (,@(map (lambda (x) (list x #f)) vars)) ,@(map (lambda (x) (if (and (pair? x) (eq? (car x) 'my-define)) (cons 'set! (cdr x)) x)) code)))) but make it recurse (this only works if all the my-define's are at the top level). -- Alex _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-06-26 2:25 ` Alex Shinn @ 2002-06-26 13:15 ` Ken Anderson 2002-06-26 14:45 ` Lynn Winebarger 2002-06-26 14:44 ` Lynn Winebarger 1 sibling, 1 reply; 13+ messages in thread From: Ken Anderson @ 2002-06-26 13:15 UTC (permalink / raw) Cc: Timothy Hickey In Jscheme, not guile, i recently redefined (define) so that groups of internal defines are turned into let* or letrec as appropriate, so you can write code without additional indenting: (define (graph) (define objRoot (BranchGroup.)) (define objTrans (TransformGroup.)) (define (addToRoot obj) (.addChild objRoot obj)) (.setCapability objTrans TransformGroup.ALLOW_TRANSFORM_WRITE$) (.addToRoot objTrans) (.addChild objTrans (ColorCube. 0.4)) (define yAxis (Transform3D.)) (define rotationAlpha (Alpha. -1 4000L)) (define rotator (RotationInterpolator. rotationAlpha objTrans yAxis 0.0f (* 2.0F (.floatValue Math.PI$)))) (define bounds (BoundingSphere. (Point3d. 0.0 0.0 0.0) 100.0)) (.setSchedulingBounds rotator bounds) (addToRoot rotator) (.compile objRoot) objRoot) At 10:25 PM 6/25/2002, Alex Shinn wrote: > >>>>> "Paul" == Paul Jarc <prj@po.cwru.edu> writes: > > Paul> I'm looking for something like Perl's "my": > > [...] > > Paul> (new-scope > Paul> (my-define foo #t) > Paul> (do-random-stuff-with foo) > Paul> (my-define bar foo) > Paul> (do-other-stuff-with bar)) > >let* can do this if you want: > > (let* ((foo #t) > (dummy (do-random-stuff-with foo)) > (bar foo)) > (do-other-stuff-with bar)) > >but that's rather poor style. If you just want bar to be some function >of foo, you can do > > (let* ((foo #t) > (bar (some-random-function-of foo))) > (do-other-stuff-with bar)) > >or you can declare all the variables you need up front > > (let* ((foo #t) (bar #f)) > (do-random-stuff-with foo) > (set! bar foo) > (do-other-stuff-with bar)) > >or nest let > > (let ((foo #t)) > (do-random-stuff-with foo) > (let ((bar foo)) > (do-other-stuff-with bar))) > >I guess that's the real complaint... nested lets indent the code too >much, but for some straight but very long procedural algorithms it's >less clear to make all the variable decls up front when their use is >localized. > >You can write new-scope as a low-level macro that walks the code, >turning my-define into set! and accumulating all the variable names used >into one top-level let. Something like > >(define-macro (new-scope . code) > (let ((vars (map cadr (filter (lambda (x) (eq? (car x) 'my-define)) > code)))) > `(let (,@(map (lambda (x) (list x #f)) vars)) > ,@(map (lambda (x) (if (and (pair? x) (eq? (car x) 'my-define)) > (cons 'set! (cdr x)) > x)) > code)))) > >but make it recurse (this only works if all the my-define's are at the >top level). > >-- >Alex > >_______________________________________________ >Guile-user mailing list >Guile-user@gnu.org >http://mail.gnu.org/mailman/listinfo/guile-user _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-06-26 13:15 ` Ken Anderson @ 2002-06-26 14:45 ` Lynn Winebarger 2002-07-02 15:34 ` Ken Anderson 0 siblings, 1 reply; 13+ messages in thread From: Lynn Winebarger @ 2002-06-26 14:45 UTC (permalink / raw) On Wednesday 26 June 2002 08:15, Ken Anderson wrote: > In Jscheme, not guile, i recently redefined (define) so that groups of > internal defines are turned into let* or letrec as appropriate, so you can > write code without additional indenting: How do you handle (let () (define (even? x) (if (= x 0) #t (not (odd? (- x 1))))) (define foo (even? 7)) (define (odd? x) (if (= x 1) #t (not (even? (- x 1)))))) Lynn _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-06-26 14:45 ` Lynn Winebarger @ 2002-07-02 15:34 ` Ken Anderson 0 siblings, 0 replies; 13+ messages in thread From: Ken Anderson @ 2002-07-02 15:34 UTC (permalink / raw) Cc: Timothy Hickey At 10:45 AM 6/26/2002, Lynn Winebarger wrote: >On Wednesday 26 June 2002 08:15, Ken Anderson wrote: > > In Jscheme, not guile, i recently redefined (define) so that groups of > > internal defines are turned into let* or letrec as appropriate, so you can > > write code without additional indenting: > >How do you handle >(let () > (define (even? x) (if (= x 0) #t (not (odd? (- x 1))))) > (define foo (even? 7)) > (define (odd? x) (if (= x 1) #t (not (even? (- x 1)))))) Rather than let, say define. (define (?) ...) This would be converted into (letrec ((even? (lambda (x) (if (= x 0) #t (not (odd? (- x 1))))))) (let* ((foo (even? 7))) (letrec ((odd? (lambda (x) (if (= x 1) #t (not (even? (- x 1))))))))))) Procedures that refer to each other should be declared in a group, as is usually done with letrec. _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-06-26 2:25 ` Alex Shinn 2002-06-26 13:15 ` Ken Anderson @ 2002-06-26 14:44 ` Lynn Winebarger 2002-06-27 1:28 ` Alex Shinn 1 sibling, 1 reply; 13+ messages in thread From: Lynn Winebarger @ 2002-06-26 14:44 UTC (permalink / raw) On Tuesday 25 June 2002 21:25, Alex Shinn wrote: > I guess that's the real complaint... nested lets indent the code too > much, but for some straight but very long procedural algorithms it's > less clear to make all the variable decls up front when their use is > localized. If it's very procedural, why is it indented so far that nested lets will indent the code "too much"? And how is not indenting new scopes going to clarify where "localized" definitions come from? (Where "localized" is visual only, as the declaration extends to the end of the enclosing block). Of course, he can do whatever he wants. > You can write new-scope as a low-level macro that walks the code, > turning my-define into set! and accumulating all the variable names used > into one top-level let. Something like > > (define-macro (new-scope . code) > (let ((vars (map cadr (filter (lambda (x) (eq? (car x) 'my-define)) > code)))) > `(let (,@(map (lambda (x) (list x #f)) vars)) > ,@(map (lambda (x) (if (and (pair? x) (eq? (car x) 'my-define)) > (cons 'set! (cdr x)) > x)) > code)))) > > but make it recurse (this only works if all the my-define's are at the > top level). If you must, why not call it "perl-scope" and introduce "my" as a syntax keyword (as is "(my x 'initial-value-here)"). And I would suggest not fully recursing - you do (presumably) still want the various let forms to introduce new scopes. Recursing over begins and ifs should be sufficient. Although perl has it's own rules for how my variables scope (like introducing them as the iteration variable in a loop), you might want to imitate those as well. Also, what happens if the variable is used before declared? Will that be an error? That _would_ require full recursion. Lynn _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-06-26 14:44 ` Lynn Winebarger @ 2002-06-27 1:28 ` Alex Shinn 0 siblings, 0 replies; 13+ messages in thread From: Alex Shinn @ 2002-06-27 1:28 UTC (permalink / raw) Cc: guile-user >>>>> "Lynn" == Lynn Winebarger <owinebar@free-expression.org> writes: Lynn> On Tuesday 25 June 2002 21:25, Alex Shinn wrote: >> I guess that's the real complaint... nested lets indent the code >> too much, but for some straight but very long procedural >> algorithms it's less clear to make all the variable decls up >> front when their use is localized. Lynn> If it's very procedural, why is it indented so far that nested Lynn> lets will indent the code "too much"? Procedural code doesn't imply you don't need new variables... in fact in procedural code you tend to use variables and state much more than functional code. The notion that lots of indentation shows good code is vastly over-simplified. I don't know what the OP's use for this was, but I have seen code where Perl style variable declarations right before their use is more readable. Consider a quick and dirty CGI script, which in Perl may follow a form like: my $foo = computeFoo(); print funcOfFoo1($foo); ... print funcOfFooN($foo); my $bar = computeBar($foo); print funcOfBar1($bar); ... print funcOfBarN($bar); This is, of course, a matter of style, but I find in these cases it helps to define bar and initialize it right before the section it's used in, rather than at the top where foo is initialized. Each block is thus isolated and easier to read. Some people will say this is ugly, unfactored code, and it would be better to pull out all the funcOfFoo's together and funcOfBar's into an enclosing function, but that's just blindly following principles without understanding them. Why break up code that only gets used in one place? It just causes more to read and more moving back and forth between source code. And I'm not alone in this, a lot of Perl gets written in this style. Then again, a lot of Perl is used for things like quick and dirty CGI scripts :) Lynn> And how is not indenting new scopes going to clarify where Lynn> "localized" definitions come from? (Where "localized" is Lynn> visual only, as the declaration extends to the end of the Lynn> enclosing block). Extra lines between each block, as above, helps. Also using the more readable define-my or some such that will stand out with syntax highlighting would be good. -- Alex _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-06-25 22:19 macro like "my" in Perl Paul Jarc 2002-06-25 23:16 ` Robert Uhl <ruhl@4dv.net> 2002-06-26 2:25 ` Alex Shinn @ 2002-07-12 20:43 ` Paul Jarc 2002-07-13 0:09 ` Neil Jerram 2 siblings, 1 reply; 13+ messages in thread From: Paul Jarc @ 2002-07-12 20:43 UTC (permalink / raw) Thanks for the input. The scoping of identifiers in top-level defines is close enough to what I want, so I ended up with this macro to wrap all top-level forms, rather than trying to modify the scoping of internal bindings. (define-macro (top-scope . exprs) (let loop ((vars (map (lambda (expr) (and (pair? expr) (member (car expr) '(define define* define-macro)) (let ((x (cdr expr))) (and (pair? x) (let ((x (car x))) (cond ((symbol? x) x) ((pair? x) (let ((x (car x))) (and (symbol? x) x))) (#t #f))))))) exprs))) (if (null? vars) #t (let ((sym (car vars)) (rest (cdr vars))) (if (and sym (member sym rest)) (scm-error 'misc-error "top-scope" "duplicate bindings: ~S" `(,sym) #f)) (loop rest)))) `(begin ,@exprs)) I don't suppose there's any way to find line numbers for the error message, is there? paul _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-07-12 20:43 ` Paul Jarc @ 2002-07-13 0:09 ` Neil Jerram 2002-07-13 20:48 ` Paul Jarc 0 siblings, 1 reply; 13+ messages in thread From: Neil Jerram @ 2002-07-13 0:09 UTC (permalink / raw) >>>>> "Paul" == Paul Jarc <prj@po.cwru.edu> writes: Paul> I don't suppose there's any way to find line numbers for the error Paul> message, is there? Yes, assuming that you haven't disabled the recording of source properties. Anything that created a pair (or list, or improper list ...) when it was read has the filename, line and column number of the pair's opening parenthesis recorded as a `source property'. Here's an example of how to access the information. guile> (define-macro (list-no-pairs . elements) (let loop ((elts elements)) (if (null? elts) (cons 'list elements) (if (pair? (car elts)) (error (format #f "Bad element ~S at ~A:~A:~A" (car elts) (source-property (car elts) 'filename) (source-property (car elts) 'line) (source-property (car elts) 'column))) (loop (cdr elts)))))) guile> (list-no-pairs 1 2 3) (1 2 3) guile> (list-no-pairs 1 (2 2) 3) standard input:25:20: In procedure error in expression (error (format #f "Bad element ~S at ~A:~A:~A" ...)): standard input:25:20: Bad element (2 2) at standard input:36:17 ABORT: (misc-error) guile> Neil _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-07-13 0:09 ` Neil Jerram @ 2002-07-13 20:48 ` Paul Jarc 2002-07-16 20:49 ` Neil Jerram 0 siblings, 1 reply; 13+ messages in thread From: Paul Jarc @ 2002-07-13 20:48 UTC (permalink / raw) Neil Jerram <neil@ossau.uklinux.net> wrote: > (error (format #f "Bad element ~S at ~A:~A:~A" > (car elts) > (source-property (car elts) 'filename) > (source-property (car elts) 'line) > (source-property (car elts) 'column))) Great, this works. Although in my guile (1.5.6), this seems to be disabled by default, so I had to add (read-enable 'positions). > guile> (list-no-pairs 1 (2 2) 3) > standard input:25:20: In procedure error in expression (error (format #f "Bad element ~S at ~A:~A:~A" ...)): > standard input:25:20: Bad element (2 2) at standard input:36:17 > ABORT: (misc-error) My error messages look like: ERROR: Bad element (2 2) at ./script:21:11 How do you get the filename and positions at the beginning of the line? paul _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-07-13 20:48 ` Paul Jarc @ 2002-07-16 20:49 ` Neil Jerram 2002-07-16 21:05 ` Paul Jarc 0 siblings, 1 reply; 13+ messages in thread From: Neil Jerram @ 2002-07-16 20:49 UTC (permalink / raw) >>>>> "Paul" == Paul Jarc <prj@po.cwru.edu> writes: Paul> Neil Jerram <neil@ossau.uklinux.net> wrote: >> (error (format #f "Bad element ~S at ~A:~A:~A" >> (car elts) >> (source-property (car elts) 'filename) >> (source-property (car elts) 'line) >> (source-property (car elts) 'column))) Paul> Great, this works. Although in my guile (1.5.6), this seems to be Paul> disabled by default, so I had to add (read-enable 'positions). guile> (list-no-pairs 1 (2 2) 3) >> standard input:25:20: In procedure error in expression (error (format #f "Bad element ~S at ~A:~A:~A" ...)): >> standard input:25:20: Bad element (2 2) at standard input:36:17 >> ABORT: (misc-error) Paul> My error messages look like: Paul> ERROR: Bad element (2 2) at ./script:21:11 Paul> How do you get the filename and positions at the beginning of the Paul> line? Sorry, I don't understand. What exactly do you want it to look like? Neil _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: macro like "my" in Perl 2002-07-16 20:49 ` Neil Jerram @ 2002-07-16 21:05 ` Paul Jarc 0 siblings, 0 replies; 13+ messages in thread From: Paul Jarc @ 2002-07-16 21:05 UTC (permalink / raw) Neil Jerram <neil@ossau.uklinux.net> wrote: >>>>>> "Paul" == Paul Jarc <prj@po.cwru.edu> writes: > Paul> Neil Jerram <neil@ossau.uklinux.net> wrote: > >> guile> (list-no-pairs 1 (2 2) 3) > >> standard input:25:20: In procedure error in expression (error (format #f "Bad element ~S at ~A:~A:~A" ...)): > >> standard input:25:20: Bad element (2 2) at standard input:36:17 > >> ABORT: (misc-error) > > Paul> My error messages look like: > Paul> ERROR: Bad element (2 2) at ./script:21:11 > > Paul> How do you get the filename and positions at the beginning of the > Paul> line? > > Sorry, I don't understand. What exactly do you want it to look like? Your error message has "standard input:25:20" at the beginning of the line, where mine has "ERROR". But I just tried again, interactively this time, and I get the filename and positions now. So I guess I'm looking for a way to enable this for scripts as well. paul _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://mail.gnu.org/mailman/listinfo/guile-user ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2002-07-16 21:05 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2002-06-25 22:19 macro like "my" in Perl Paul Jarc 2002-06-25 23:16 ` Robert Uhl <ruhl@4dv.net> 2002-06-26 2:25 ` Alex Shinn 2002-06-26 13:15 ` Ken Anderson 2002-06-26 14:45 ` Lynn Winebarger 2002-07-02 15:34 ` Ken Anderson 2002-06-26 14:44 ` Lynn Winebarger 2002-06-27 1:28 ` Alex Shinn 2002-07-12 20:43 ` Paul Jarc 2002-07-13 0:09 ` Neil Jerram 2002-07-13 20:48 ` Paul Jarc 2002-07-16 20:49 ` Neil Jerram 2002-07-16 21:05 ` Paul Jarc
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).