unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Define in let
@ 2013-08-20 16:39 Dmitry Bogatov
  2013-08-20 16:57 ` Thompson, David
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Dmitry Bogatov @ 2013-08-20 16:39 UTC (permalink / raw)
  To: guile-user

[-- Attachment #1: Type: text/plain, Size: 536 bytes --]


It seems following is invalid:

   (let ((a 2))
        (define (foo x) (+ a x)))

I prefer to reduce scope of variable as much as possible, so
I find this restriction unconvinent. Is is part of standard or technical
limitation? Is it any workaround?

Please, keep in CC, I am not subscribed.

--
Best regards, Dmitry Bogatov <KAction@gnu.org>,
Free Software supporter and netiquette guardian.
	git clone git://kaction.name/rc-files.git --depth 1
	GPG: 54B7F00D
Html mail and proprietary format attachments are forwarded to /dev/null.

[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-20 16:39 Define in let Dmitry Bogatov
@ 2013-08-20 16:57 ` Thompson, David
  2013-08-20 17:02 ` Taylan Ulrich B.
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Thompson, David @ 2013-08-20 16:57 UTC (permalink / raw)
  To: Dmitry Bogatov; +Cc: Guile User

[-- Attachment #1: Type: text/plain, Size: 863 bytes --]

On Tue, Aug 20, 2013 at 12:39 PM, Dmitry Bogatov <KAction@gnu.org> wrote:

>
> It seems following is invalid:
>
>    (let ((a 2))
>         (define (foo x) (+ a x)))
>
> I prefer to reduce scope of variable as much as possible, so
> I find this restriction unconvinent. Is is part of standard or technical
> limitation? Is it any workaround?
>


The problem is that you have an invalid `let` form. You need an expression
besides `define`.

Something like this would be valid:

(let ((a 2))
  (define (foo x) (+ a x))
  (foo 4))


>
> Please, keep in CC, I am not subscribed.
>
> --
> Best regards, Dmitry Bogatov <KAction@gnu.org>,
> Free Software supporter and netiquette guardian.
>         git clone git://kaction.name/rc-files.git --depth 1
>         GPG: 54B7F00D
> Html mail and proprietary format attachments are forwarded to /dev/null.
>

- Dave Thompson

[-- Attachment #2: Type: text/html, Size: 1559 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-20 16:39 Define in let Dmitry Bogatov
  2013-08-20 16:57 ` Thompson, David
@ 2013-08-20 17:02 ` Taylan Ulrich B.
  2013-08-20 17:18 ` John B. Brodie
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Taylan Ulrich B. @ 2013-08-20 17:02 UTC (permalink / raw)
  To: Dmitry Bogatov; +Cc: guile-user

Dmitry Bogatov <KAction@gnu.org> writes:

> It seems following is invalid:
>
>    (let ((a 2))
>         (define (foo x) (+ a x)))
>
> I prefer to reduce scope of variable as much as possible, so
> I find this restriction unconvinent. Is is part of standard or technical
> limitation? Is it any workaround?
>
> Please, keep in CC, I am not subscribed.
>
> --
> Best regards, Dmitry Bogatov <KAction@gnu.org>,
> Free Software supporter and netiquette guardian.
> 	git clone git://kaction.name/rc-files.git --depth 1
> 	GPG: 54B7F00D
> Html mail and proprietary format attachments are forwarded to /dev/null.

No Scheme standard so far has supported such a thing, and neither Guile.

It would be neat, I had the idea too (it would allow re-use of the
semantics of `begin' and thus be coherent/orthogonal in a way), but I
think it's a non-trivial change, probably both to the implementation of
Guile and the semantics for `let' that have been well-understood ever
since very old Lisps: that `let' is a thin wrapper around a call to an
in-place `lambda'.

(let ((a x)
      (b y))
  ...)

is just

((lambda (a b)
   ...)
 x y)

in pretty much any Lisp.

Note that you can do

(define foo
  (let ((a 2))
    (lambda (x) (+ a x))))

and if you want to define multiple things that use that `a' binding, you
could use `define-values', but Guile doesn't have that yet (there's a
hacky in-Scheme definition in R7RS-small if you want something quick):

(define-values (foo bar)
  (let ((a 2))
    (values
     (lambda (x) (+ a x))
     (lambda (y) (* a y)))))

Taylan



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-20 16:39 Define in let Dmitry Bogatov
  2013-08-20 16:57 ` Thompson, David
  2013-08-20 17:02 ` Taylan Ulrich B.
@ 2013-08-20 17:18 ` John B. Brodie
  2013-08-20 17:19 ` Ian Price
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: John B. Brodie @ 2013-08-20 17:18 UTC (permalink / raw)
  To: Dmitry Bogatov; +Cc: guile-user

On 08/20/2013 12:39 PM, Dmitry Bogatov wrote:
> It seems following is invalid:
>
>    (let ((a 2))
>         (define (foo x) (+ a x)))
>
> I prefer to reduce scope of variable as much as possible, so
> I find this restriction unconvinent. Is is part of standard or technical
> limitation? Is it any workaround?

use a lambda form rather than a define:

(letrec ((a 2)
             (foo (lambda (x) (+ a x))))
     (foo 3))

>
> Please, keep in CC, I am not subscribed.
>
> --
> Best regards, Dmitry Bogatov <KAction@gnu.org>,
> Free Software supporter and netiquette guardian.
> 	git clone git://kaction.name/rc-files.git --depth 1
> 	GPG: 54B7F00D
> Html mail and proprietary format attachments are forwarded to /dev/null.




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-20 16:39 Define in let Dmitry Bogatov
                   ` (2 preceding siblings ...)
  2013-08-20 17:18 ` John B. Brodie
@ 2013-08-20 17:19 ` Ian Price
  2013-08-20 17:52 ` Mike Gran
  2013-08-20 21:01 ` David Pirotte
  5 siblings, 0 replies; 14+ messages in thread
From: Ian Price @ 2013-08-20 17:19 UTC (permalink / raw)
  To: Dmitry Bogatov; +Cc: guile-user

Dmitry Bogatov <KAction@gnu.org> writes:

> It seems following is invalid:
>
>    (let ((a 2))
>         (define (foo x) (+ a x)))
>
> I prefer to reduce scope of variable as much as possible, so
> I find this restriction unconvinent. Is is part of standard or technical
> limitation? Is it any workaround?

It's not a limitation, but a misunderstanding. Define creates a binding
in the _current_ scope, not the top level one.


-- 
Ian Price -- shift-reset.com

"Programming is like pinball. The reward for doing it well is
the opportunity to do it again" - from "The Wizardy Compiled"



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-20 16:39 Define in let Dmitry Bogatov
                   ` (3 preceding siblings ...)
  2013-08-20 17:19 ` Ian Price
@ 2013-08-20 17:52 ` Mike Gran
  2013-08-20 21:01 ` David Pirotte
  5 siblings, 0 replies; 14+ messages in thread
From: Mike Gran @ 2013-08-20 17:52 UTC (permalink / raw)
  To: Dmitry Bogatov, guile-user@gnu.org

> From: Dmitry Bogatov <KAction@gnu.org>

> It seems following is invalid:
> 
>    (let ((a 2))
>         (define (foo x) (+ a x)))
> 

Perhaps something like

(let* ((a 2)
       (foo (lambda (x) (+ a x))))
  (foo 

-Mike




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-20 16:39 Define in let Dmitry Bogatov
                   ` (4 preceding siblings ...)
  2013-08-20 17:52 ` Mike Gran
@ 2013-08-20 21:01 ` David Pirotte
  2013-08-21  6:52   ` Panicz Maciej Godek
  2013-08-21 15:42   ` Dmitry Bogatov
  5 siblings, 2 replies; 14+ messages in thread
From: David Pirotte @ 2013-08-20 21:01 UTC (permalink / raw)
  To: Dmitry Bogatov; +Cc: guile-user

Hello,

> It seems following is invalid:
> 
>    (let ((a 2))
>         (define (foo x) (+ a x)))
> 
> I prefer to reduce scope of variable as much as possible, so
> I find this restriction unconvinent. Is is part of standard or technical
> limitation? Is it any workaround?

Section '3.4.7 Example 2: A Shared Persistent Variable' is probably what you want?

Cheers,
David



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-20 21:01 ` David Pirotte
@ 2013-08-21  6:52   ` Panicz Maciej Godek
  2013-08-21  6:55     ` Panicz Maciej Godek
  2013-08-21  9:28     ` Ralf Mattes
  2013-08-21 15:42   ` Dmitry Bogatov
  1 sibling, 2 replies; 14+ messages in thread
From: Panicz Maciej Godek @ 2013-08-21  6:52 UTC (permalink / raw)
  To: David Pirotte; +Cc: guile-user@gnu.org, Dmitry Bogatov

[-- Attachment #1: Type: text/plain, Size: 1971 bytes --]

2013/8/20 David Pirotte <david@altosw.be>

> Hello,
>
> > It seems following is invalid:
> >
> >    (let ((a 2))
> >         (define (foo x) (+ a x)))
> >
> > I prefer to reduce scope of variable as much as possible, so
> > I find this restriction unconvinent. Is is part of standard or technical
> > limitation? Is it any workaround?
>

The Scheme's idiomatic way to achieve the effect that you
probably want would be
(define foo #f)
(let ((a 2))
  (set! foo (lambda (x) (+ a x))))

Although it allows to achieve the desired effect, it doesn't
express the programmer's intention quite clearly.
If you're interested, I recently wrote a macro that would
allow to get the same in a IMHO slightly more elegant way, i.e.

(publish
  (define (foo x) (+ a x))
 where
  (define a 2))

The macro's definition (procedural) follows.
Regards.

=============================
(define-macro (publish . definitions)
  (define (interface-name interface)
    (match interface
      ((head . tail)
       (interface-name head))
      ((? symbol? name)
       name)))
  (let-values (((public-definitions where&private-definitions)
                (split-before (equals? 'where) definitions)))
    `(begin ,@(map (match-lambda
                       ((define-variant interface . body)
                        `(define ,(interface-name interface) #f)))
                   public-definitions)
            (let ()
              ,@(match where&private-definitions
                  (('where . private-definitions)
                   private-definitions)
                  (() '()))
              ,@(map (match-lambda
                         ((define-variant interface . body)
                          (let ((name (interface-name interface)))
                            `(set! ,name
                                   (let ()
                                     (,define-variant ,interface . ,body)
                                     ,name)))))
                     public-definitions)))))

[-- Attachment #2: Type: text/html, Size: 2967 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-21  6:52   ` Panicz Maciej Godek
@ 2013-08-21  6:55     ` Panicz Maciej Godek
  2013-08-21  9:28     ` Ralf Mattes
  1 sibling, 0 replies; 14+ messages in thread
From: Panicz Maciej Godek @ 2013-08-21  6:55 UTC (permalink / raw)
  To: David Pirotte; +Cc: guile-user@gnu.org, Dmitry Bogatov

[-- Attachment #1: Type: text/plain, Size: 330 bytes --]

Sorry, the macro definition relies on a few additional functions,
in particular on the (ice-9 match) and (srfi srfi-1) modules and
the following definitions:

(define (split-before criterion list)
  (split-at list (or (list-index criterion list)
                     (length list))))

(define (equals? x) (lambda(y)(equal? x y)))

[-- Attachment #2: Type: text/html, Size: 469 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-21  6:52   ` Panicz Maciej Godek
  2013-08-21  6:55     ` Panicz Maciej Godek
@ 2013-08-21  9:28     ` Ralf Mattes
  2013-08-21 10:17       ` Panicz Maciej Godek
  1 sibling, 1 reply; 14+ messages in thread
From: Ralf Mattes @ 2013-08-21  9:28 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: guile-user@gnu.org, Dmitry Bogatov, David Pirotte

On Wed, Aug 21, 2013 at 08:52:02AM +0200, Panicz Maciej Godek wrote:
> 2013/8/20 David Pirotte <david@altosw.be>
> 
> > Hello,
> >
> > > It seems following is invalid:
> > >
> > >    (let ((a 2))
> > >         (define (foo x) (+ a x)))
> > >
> > > I prefer to reduce scope of variable as much as possible, so
> > > I find this restriction unconvinent. Is is part of standard or technical
> > > limitation? Is it any workaround?
> >
> 
> The Scheme's idiomatic way to achieve the effect that you
> probably want would be
> (define foo #f)
> (let ((a 2))
>   (set! foo (lambda (x) (+ a x))))

I'd say this is extremly contorted and non-schemish.
What's wrong with:

  (define foo
         (let ((a 2))
           (lambda (arg) (+ a arg))))

This is the basic let-over-lambda closure ....

Cheers, Ralf Mattes




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-21  9:28     ` Ralf Mattes
@ 2013-08-21 10:17       ` Panicz Maciej Godek
  2013-08-21 10:32         ` Ralf Mattes
  0 siblings, 1 reply; 14+ messages in thread
From: Panicz Maciej Godek @ 2013-08-21 10:17 UTC (permalink / raw)
  To: Ralf Mattes; +Cc: guile-user@gnu.org, Dmitry Bogatov, David Pirotte

[-- Attachment #1: Type: text/plain, Size: 2172 bytes --]

2013/8/21 Ralf Mattes <rm@seid-online.de>

> On Wed, Aug 21, 2013 at 08:52:02AM +0200, Panicz Maciej Godek wrote:
> > 2013/8/20 David Pirotte <david@altosw.be>
> >
> > > Hello,
> > >
> > > > It seems following is invalid:
> > > >
> > > >    (let ((a 2))
> > > >         (define (foo x) (+ a x)))
> > > >
> > > > I prefer to reduce scope of variable as much as possible, so
> > > > I find this restriction unconvinent. Is is part of standard or
> technical
> > > > limitation? Is it any workaround?
> > >
> >
> > The Scheme's idiomatic way to achieve the effect that you
> > probably want would be
> > (define foo #f)
> > (let ((a 2))
> >   (set! foo (lambda (x) (+ a x))))
>
> I'd say this is extremly contorted and non-schemish.
> What's wrong with:
>
>   (define foo
>          (let ((a 2))
>            (lambda (arg) (+ a arg))))
>
> This is the basic let-over-lambda closure ....
>
>
You're right, but it only works if you want to export only one symbol
from a lexical scope. If you wanted a few procedures accessing
a single scope, you'd either need to use the solution with 'set!',
or -- as Taylan suggested -- have a "define-values" form.

Actually, I think should also be possible to write a "define-values"
macro using the method I presented

(define-macro (define-values symbols . body)
  (let ((value-identifiers (map gensym (map symbol->string symbols))))
    `(begin
       ,@(map (lambda(x)`(define ,x #f)) symbols)
       (let-values ((,value-identifiers ,@body))
         ,@(map (lambda(symbol value)`(set! ,symbol ,value))
                symbols
                value-identifiers)))))

So we can say that guile already has that ;]
I don't know however how to write this using define-syntax, the
idea is to transform
(define-values (symbol1 symbol2 ...) body ...)
into
(begin
  (define symbol1 #f)
  (define symbol2 #f)
  ...
  (let-values (((value1 value2 ...) (begin body ...))
    (set! symbol1 value1)
    (set! symbol2 value2)
    ...)

but somehow we need to generate identifiers for symbol1 symbol2 ...
(here I wrote symbolically value1 value2 ..., but I'd appreciate if someone
more competent could provide a syntax-rules-based solution)

regards

[-- Attachment #2: Type: text/html, Size: 3368 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-21 10:17       ` Panicz Maciej Godek
@ 2013-08-21 10:32         ` Ralf Mattes
  2013-08-21 11:01           ` Panicz Maciej Godek
  0 siblings, 1 reply; 14+ messages in thread
From: Ralf Mattes @ 2013-08-21 10:32 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: guile-user@gnu.org

On Wed, Aug 21, 2013 at 12:17:43PM +0200, Panicz Maciej Godek wrote:
> You're right, but it only works if you want to export only one symbol
> from a lexical scope. If you wanted a few procedures accessing
> a single scope, you'd either need to use the solution with 'set!',
> or -- as Taylan suggested -- have a "define-values" form.

Yes, but was that the OP's question?

> Actually, I think should also be possible to write a "define-values"
> macro using the method I presented
[... snip ...]
> but somehow we need to generate identifiers for symbol1 symbol2 ...
> (here I wrote symbolically value1 value2 ..., but I'd appreciate if someone
> more competent could provide a syntax-rules-based solution)

Maybe it's time to point out that this question is in the Scheme-FAQ ;-)
[http://community.schemewiki.org/?scheme-faq-language] - Section 
"Is there a way to define top-level closures?" (sorry, bad webdesign,
no wa to link directlyto the topic). The answer not only mentions 
'define-values but also links to an implementation:
[http://community.schemewiki.org/?scheme-faq-macros#multidefine]
that uses 'syntax-rules

HTH RalfD





^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-21 10:32         ` Ralf Mattes
@ 2013-08-21 11:01           ` Panicz Maciej Godek
  0 siblings, 0 replies; 14+ messages in thread
From: Panicz Maciej Godek @ 2013-08-21 11:01 UTC (permalink / raw)
  To: Ralf Mattes; +Cc: guile-user@gnu.org

[-- Attachment #1: Type: text/plain, Size: 1449 bytes --]

2013/8/21 Ralf Mattes <rm@seid-online.de>

> On Wed, Aug 21, 2013 at 12:17:43PM +0200, Panicz Maciej Godek wrote:
> > You're right, but it only works if you want to export only one symbol
> > from a lexical scope. If you wanted a few procedures accessing
> > a single scope, you'd either need to use the solution with 'set!',
> > or -- as Taylan suggested -- have a "define-values" form.
>
> Yes, but was that the OP's question?
>
>
Well, if the question is "to reduce scope of variable as much as possible",
then I think that the issue of defining multiple procedures within the same
scope is a part of that question, even if it wasn't posited directly


> > Actually, I think should also be possible to write a "define-values"
> > macro using the method I presented
> [... snip ...]
> > but somehow we need to generate identifiers for symbol1 symbol2 ...
> > (here I wrote symbolically value1 value2 ..., but I'd appreciate if
> someone
> > more competent could provide a syntax-rules-based solution)
>
> Maybe it's time to point out that this question is in the Scheme-FAQ ;-)
> [http://community.schemewiki.org/?scheme-faq-language] - Section
> "Is there a way to define top-level closures?" (sorry, bad webdesign,
> no wa to link directlyto the topic). The answer not only mentions
> 'define-values but also links to an implementation:
> [http://community.schemewiki.org/?scheme-faq-macros#multidefine]
> that uses 'syntax-rules
>
> Thanks! :)

[-- Attachment #2: Type: text/html, Size: 2738 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Define in let
  2013-08-20 21:01 ` David Pirotte
  2013-08-21  6:52   ` Panicz Maciej Godek
@ 2013-08-21 15:42   ` Dmitry Bogatov
  1 sibling, 0 replies; 14+ messages in thread
From: Dmitry Bogatov @ 2013-08-21 15:42 UTC (permalink / raw)
  To: David Pirotte; +Cc: guile-user

[-- Attachment #1: Type: text/plain, Size: 797 bytes --]


>> It seems following is invalid:
>>
>>    (let ((a 2))
>>         (define (foo x) (+ a x)))
>>
>> I prefer to reduce scope of variable as much as possible, so
>> I find this restriction unconvinent. Is is part of standard or technical
>> limitation? Is it any workaround?
>
> Section '3.4.7 Example 2: A Shared Persistent Variable' is probably what you want?
Yes, although it is a bit too verbose.
(define (foo x)
        (let ((a 2))
             (+ a x0)))
is enough for my puroses, although solution about define-values seems
intresting. Thanks all!

--
Best regards, Dmitry Bogatov <KAction@gnu.org>,
Free Software supporter and netiquette guardian.
	git clone git://kaction.name/rc-files.git --depth 1
	GPG: 54B7F00D
Html mail and proprietary format attachments are forwarded to /dev/null.

[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-08-21 15:42 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-20 16:39 Define in let Dmitry Bogatov
2013-08-20 16:57 ` Thompson, David
2013-08-20 17:02 ` Taylan Ulrich B.
2013-08-20 17:18 ` John B. Brodie
2013-08-20 17:19 ` Ian Price
2013-08-20 17:52 ` Mike Gran
2013-08-20 21:01 ` David Pirotte
2013-08-21  6:52   ` Panicz Maciej Godek
2013-08-21  6:55     ` Panicz Maciej Godek
2013-08-21  9:28     ` Ralf Mattes
2013-08-21 10:17       ` Panicz Maciej Godek
2013-08-21 10:32         ` Ralf Mattes
2013-08-21 11:01           ` Panicz Maciej Godek
2013-08-21 15:42   ` Dmitry Bogatov

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).