* Re: C++ declaration style programming?
2004-01-20 22:17 Han-Wen Nienhuys
@ 2004-01-21 3:58 ` Viktor Pavlenko
2004-01-21 12:40 ` Han-Wen Nienhuys
2004-01-21 4:57 ` Issac Trotts
` (3 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Viktor Pavlenko @ 2004-01-21 3:58 UTC (permalink / raw)
Cc: guile-user
>>>>> "HN" == Han-Wen Nienhuys <hanwen@xs4all.nl> writes:
HN> Usually in C++, I do
HN> int var1 = something ();
HN> int var2 = something (var1);
HN> int var3 = something (var1, var2);
HN> etc.
HN> in Scheme, this translates quite well to (let* ) :
HN> (let*
HN> ((var1 (something))
HN> (var2 (something var1))
HN> (var3 (something var1 var2)))
HN> .. )
HN> However, it doesn't work so well when I mix commands with
HN> declarations, eg.
HN> int var1 = something ();
HN> var1 += 2;
HN> int var2 = something (var1);
HN> var2 += var1;
HN> int var3 = something (var1, var2);
HN> etc.
I think the following still looks OK and cleaner than the C above:
(let* ((var1 (+ (something) 2))
(var2 (+ (something var1) var1))
(var3 (something var1 var2)))
If you need to change var3 at a later point, just give it another name:
(let ((var3-2 (+ (something-else var3))))
(...
instead of set!-ting it. The problem with set! in a lexically scoped
language is that you can change the binding of a variable defined at a
higher level by mistake:
guile> (define a 123)
guile> a
123
guile> (let ((a 111)) (set! a 444)) ;;works as expected
guile> a
123
guile> (let ((b 111)) (set! a 444)) ;;oops
guile> a
444
Lexical bindings with let and friends will never get you into this
trouble.
(Scheme gurus, please correct me if my reasoning is wrong)
HN> I would like to have some macro, where I can write the Scheme
HN> analogon like
HN> (begin-let*
HN> (def var1 (something))
HN> (set! var1 (+ var1 2))
HN> (def var2 (something var1))
HN> (set! var2 (+ var2 var1))
HN> (def var3 (something var1 var2))
HN> ... )
Probably you can define that syntax, but the passage above doesn't
look like Scheme...
--
Viktor
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C++ declaration style programming?
2004-01-21 3:58 ` Viktor Pavlenko
@ 2004-01-21 12:40 ` Han-Wen Nienhuys
0 siblings, 0 replies; 14+ messages in thread
From: Han-Wen Nienhuys @ 2004-01-21 12:40 UTC (permalink / raw)
Cc: guile-user
vvp@rogers.com writes:
>
> (let* ((var1 (+ (something) 2))
> (var2 (+ (something var1) var1))
> (var3 (something var1 var2)))
>
> If you need to change var3 at a later point, just give it another name:
>
> (let ((var3-2 (+ (something-else var3))))
> (...
>
> instead of set!-ting it. The problem with set! in a lexically scoped
> language is that you can change the binding of a variable defined at a
> higher level by mistake:
I know about all this. The example was a little contrived. The things
I have in mind are statements which currently return SCM_UNSPECIFIED.
I think it looks stupid to do
(let* ((a (something))
(unused (display a))
(b (something-else a))
..
)
which introduces a variable unused, and puts emphasis on the
declaration, not on the main action of the statements.
--
Han-Wen Nienhuys | hanwen@xs4all.nl | http://www.xs4all.nl/~hanwen
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C++ declaration style programming?
2004-01-20 22:17 Han-Wen Nienhuys
2004-01-21 3:58 ` Viktor Pavlenko
@ 2004-01-21 4:57 ` Issac Trotts
2004-01-21 5:00 ` Stephen Compall
` (2 subsequent siblings)
4 siblings, 0 replies; 14+ messages in thread
From: Issac Trotts @ 2004-01-21 4:57 UTC (permalink / raw)
On Tue, Jan 20, 2004 at 11:17:34PM +0100, Han-Wen Nienhuys wrote:
>
> Hi there,
>
> I just realized that one of the things that I dislike about Scheme is
> that my habit of naming intermediate results (which I inherited from
> C++) leads to deep nesting.
>
> Usually in C++, I do
>
> int var1 = something ();
> int var2 = something (var1);
> int var3 = something (var1, var2);
> etc.
>
> in Scheme, this translates quite well to (let* ) :
>
> (let*
> ((var1 (something))
> (var2 (something var1))
> (var3 (something var1 var2)))
> .. )
>
> However, it doesn't work so well when I mix commands with
> declarations, eg.
>
>
> int var1 = something ();
> var1 += 2;
> int var2 = something (var1);
> var2 += var1;
> int var3 = something (var1, var2);
> etc.
Well, in this case you could do something more functional:
(define (something . x) 1)
(let*
((var1 (+ 2 (something)))
(var2 (+ (something var1) var1))
(var3 (something var1 var2)))
(display `(,var1 ,var2 ,var3)))
> This can presumably be done by writing a macro begin-let* that expands
> the statement list in a suitably nested let*
>
> However, I was wondering whether there exists a standard library
> syntax mechanism that lets me write code in this fashion.
>
> --
>
> Han-Wen Nienhuys | hanwen@xs4all.nl | http://www.xs4all.nl/~hanwen
>
>
>
> _______________________________________________
> Guile-user mailing list
> Guile-user@gnu.org
> http://mail.gnu.org/mailman/listinfo/guile-user
--
Issac Trotts
http://redwood.ucdavis.edu/~issac
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C++ declaration style programming?
2004-01-20 22:17 Han-Wen Nienhuys
2004-01-21 3:58 ` Viktor Pavlenko
2004-01-21 4:57 ` Issac Trotts
@ 2004-01-21 5:00 ` Stephen Compall
2004-01-21 12:45 ` Han-Wen Nienhuys
2004-01-21 5:03 ` Lynn Winebarger
2004-01-21 21:46 ` Keith Wright
4 siblings, 1 reply; 14+ messages in thread
From: Stephen Compall @ 2004-01-21 5:00 UTC (permalink / raw)
Cc: guile-user
Han-Wen Nienhuys <hanwen@xs4all.nl> writes:
> (begin-let*
> (def var1 (something))
> (set! var1 (+ var1 2))
> (def var2 (something var1))
> (set! var2 (+ var2 var1))
> (def var3 (something var1 var2))
> ... )
>
>
> This can presumably be done by writing a macro begin-let* that expands
> the statement list in a suitably nested let*
>
> However, I was wondering whether there exists a standard library
> syntax mechanism that lets me write code in this fashion.
Viktor Pavlenko is correct in saying that this is just not what you do
in Scheme. As Stroustrup (I believe) said, you cannot simply take
idioms from one language and use them in another.
That said, here is a macro that does the thing. Note, however, that:
1. it arbitrarly interprets forms whose car is 'def to be your define
forms
2. you can re-def forms and in so doing shadow their previous
definitions (not that this makes any difference, as the scope
continues to the end of begin-let*)
3. because of 1., def forms buried deeper than the
immediate level will not be found. So (begin-let* (def hello
"hello")) is ok, (begin-let* (begin (def hello "hello") (display
hello) (newline))) is not ok.
4. also because of 1., you can't (def def newline) and expect (def)
as one of your forms to be the same as (newline). (def) will be
changed to (let (()) ...), which of course will throw
syntax-error.
5. This def doesn't include the function definition shortcut,
i.e. "having the first argument be a pair means you're defining a
function" isn't recognized. Use lambda instead. Not that you'd
do that, being so against the Schemely way of doing things >:->
I suggest you document this macro before using it.
(define-macro (begin-let* . forms)
(let ((newforms (list 'begin)))
(let lp ((forms forms) (lastpair newforms))
(cond
((not (pair? forms)) newforms)
((and (pair? (car forms)) (eq? 'def (caar forms)))
(set-cdr! lastpair `((let (,(cdar forms)))))
(lp (cdr forms) (cdadr lastpair)))
(else
(set-cdr! lastpair (list (car forms)))
(lp (cdr forms) (cdr lastpair)))))))
--
Stephen Compall or s11 or sirian
Many receive advice, few profit by it.
-- Publilius Syrus
64 Vauxhall Cross csystems passwd CDC Audiotel Skipjack tempest
Albright ARPA assassination Ft. Bragg satellite imagery clones ASIO
EuroFed
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C++ declaration style programming?
2004-01-21 5:00 ` Stephen Compall
@ 2004-01-21 12:45 ` Han-Wen Nienhuys
0 siblings, 0 replies; 14+ messages in thread
From: Han-Wen Nienhuys @ 2004-01-21 12:45 UTC (permalink / raw)
Cc: guile-user
s11@member.fsf.org writes:
> > This can presumably be done by writing a macro begin-let* that expands
> > the statement list in a suitably nested let*
> >
> > However, I was wondering whether there exists a standard library
> > syntax mechanism that lets me write code in this fashion.
>
> Viktor Pavlenko is correct in saying that this is just not what you do
> in Scheme. As Stroustrup (I believe) said, you cannot simply take
> idioms from one language and use them in another.
I'm not a fan of Stroustrup or C++, but I need to get over some gripes
that I have with Scheme. This macro can help, and if the Schemely way
of doing things is correct, then I'll find out why other ways are
wrong once I start using them. :)
Thanks for the macro definition.
> I suggest you document this macro before using it.
will do.
--
Han-Wen Nienhuys | hanwen@xs4all.nl | http://www.xs4all.nl/~hanwen
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C++ declaration style programming?
2004-01-20 22:17 Han-Wen Nienhuys
` (2 preceding siblings ...)
2004-01-21 5:00 ` Stephen Compall
@ 2004-01-21 5:03 ` Lynn Winebarger
2004-01-21 21:46 ` Keith Wright
4 siblings, 0 replies; 14+ messages in thread
From: Lynn Winebarger @ 2004-01-21 5:03 UTC (permalink / raw)
Han-Wen Nienhuys wrote:
> (begin-let*
> (def var1 (something))
> (set! var1 (+ var1 2))
> (def var2 (something var1))
> (set! var2 (+ var2 var1))
> (def var3 (something var1 var2))
> ... )
>
>
> This can presumably be done by writing a macro begin-let* that expands
> the statement list in a suitably nested let*
>
> However, I was wondering whether there exists a standard library
> syntax mechanism that lets me write code in this fashion.
>
Untested...
(define-syntax begin-let*
(syntax-rules ()
((_ args ...)
(begin-let*-helper () () (args ...)))))
(define-syntax begin-let*-helper
(syntax-rules (def)
((_ (var ...) (statement ...) ())
(let ((var #f) ...) statement ...))
((_ vars (statement ...) ((def x y) . rest))
(begin-let*-helper (x . vars) (statement ... (set! x y)) rest))
((_ vars (statement ...) (non-decl . rest))
(begin-let*-helper vars (statement ... (set! x y)) rest))))
You could be slightly more clever about reversing the statements _after_
accumulating them, rather than appending (and building the same list over
and over and over...). But I'll leave that as an easy exercise.
Odd to call it "declaration style", though.
Lynn
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: C++ declaration style programming?
2004-01-20 22:17 Han-Wen Nienhuys
` (3 preceding siblings ...)
2004-01-21 5:03 ` Lynn Winebarger
@ 2004-01-21 21:46 ` Keith Wright
4 siblings, 0 replies; 14+ messages in thread
From: Keith Wright @ 2004-01-21 21:46 UTC (permalink / raw)
> From: Han-Wen Nienhuys <hanwen@xs4all.nl>
>
> However, it doesn't work so well when I mix commands with
> declarations, eg.
>
>
> int var1 = something ();
> var1 += 2;
> int var2 = something (var1);
> var2 += var1;
> int var3 = something (var1, var2);
> etc.
>
I realize this is just an example of syntax, several people
have pointed out that computing a value of 'var1' only to
change it has some lameness to it, but if you need to do that...
(let* ((var1 (let ((var1-ini (something)))
(+ 2 var1-ini)))
(var2 (let ((var2-ini (something var1)))
(+ var2-ini var1)))
(var3 (something var1 var2)) )
etc)
You can use the first guess value as many times as you
need to compute the final value, but then it goes out
of scope and doesn't clutter all that follows.
If the imperative commands are part of computing the following
variable then...
(let* ((var1 (something))
(var2 (begin (set! var1 (+ 2 var1))
(something var1) ))
(var3 (begin (set! var2 (+ var2 var1))
(something var1 var2) )))
etc)
If the imperative stuff is not related to either the preceding
or following declaration, then maybe it should be moved out of
the middle.
Just a thought, hope this helps,
do what you will is the whole of the law.
--
-- Keith Wright <kwright@free-comp-shop.com>
Programmer in Chief, Free Computer Shop <http://www.free-comp-shop.com>
--- Food, Shelter, Source code. ---
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user
^ permalink raw reply [flat|nested] 14+ messages in thread