unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* dynamic-wind
@ 2017-06-30 20:33 Catonano
  2017-06-30 21:48 ` dynamic-wind Panicz Maciej Godek
  0 siblings, 1 reply; 14+ messages in thread
From: Catonano @ 2017-06-30 20:33 UTC (permalink / raw)
  To: guile-user

On the irc channel I was suggested that it might have been a good fit for
my use case

I took a look at it in the manual

I'm perplexed. I don't understand it

How is it supposed to be used ?

The provided example is somewhat contrived, I couldn't understand it anyway.

My use case is basic, really.

I have a scheme wrap around a C library for reading xls files, freexl.

Freexl uses a pointer to a structure tha represents the opened xls file and
its contents

Each function writes/reads in the memory region pointed to such pointer.

In the end, it requires to use a function that closes the file AND frees
all the involved structures in memory.

So my idea was that I would have gotten a simple macro, like this

(with-xls-file "path/to/my/xls-file.xls" handler-ptr
   (do-something handler-ptr)
   (do-something-more handler-ptr))

and this would have expanded to

(freexl-open "path/to/my/xls-file.xls" handler-ptr)
(freexl-do-something handler-ptr)
(freexl-do-something-more handler-ptr))
(freexl-close handler-ptr)

Do I need dynamic-wind at all ?


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

* Re: dynamic-wind
  2017-06-30 20:33 dynamic-wind Catonano
@ 2017-06-30 21:48 ` Panicz Maciej Godek
  2017-07-02  6:00   ` dynamic-wind Catonano
  0 siblings, 1 reply; 14+ messages in thread
From: Panicz Maciej Godek @ 2017-06-30 21:48 UTC (permalink / raw)
  To: Catonano; +Cc: guile-user@gnu.org

2017-06-30 22:33 GMT+02:00 Catonano <catonano@gmail.com>:

> On the irc channel I was suggested that it might have been a good fit for
> my use case
>
> I took a look at it in the manual
>
> I'm perplexed. I don't understand it
>
> How is it supposed to be used ?
>
>
It's very simple (at least from the point of view of a user)
When it is tempting to write something like

(define (within-context action)
  (enter-context)
  (action)
  (leave-context))

you simply change it to

(define (within-context action)
  (dynamic-wind
    (lambda () (enter-context))
    action
    (lambda () (leave-context))))

The thing is, that in general (action) may transfer control outside of the
scope of that particular context (like, using call/cc or exceptions) -- and
in such situations, we would like the (leave-context) handler to be
invoked. If and we ever get back there, we wish that the (enter-context)
were invoked again.



> The provided example is somewhat contrived, I couldn't understand it
> anyway.
>
> My use case is basic, really.
>
> I have a scheme wrap around a C library for reading xls files, freexl.
>
> Freexl uses a pointer to a structure tha represents the opened xls file and
> its contents
>
> Each function writes/reads in the memory region pointed to such pointer.
>
> In the end, it requires to use a function that closes the file AND frees
> all the involved structures in memory.
>
> So my idea was that I would have gotten a simple macro, like this
>
> (with-xls-file "path/to/my/xls-file.xls" handler-ptr
>    (do-something handler-ptr)
>    (do-something-more handler-ptr))
>
> and this would have expanded to
>
> (freexl-open "path/to/my/xls-file.xls" handler-ptr)
> (freexl-do-something handler-ptr)
> (freexl-do-something-more handler-ptr))
> (freexl-close handler-ptr)
>
> Do I need dynamic-wind at all ?
>

If you don't use dynamic-wind, some of the possible use cases will not be
covered. Non-local transfers of control will break the system.

I believe you'd like to assume that there shouldn't be any non-local
transfers of control, but actually you can't know this. And the interface
to dynamic-wind is very straightforward, so there's no excuse for not using
it.

Here's a simple real life example in Scheme:

(define current-working-directory getcwd)(define change-directory chdir)

(define (with-changed-working-directory dir thunk)  (let ((cwd
(current-working-directory)))    (dynamic-wind (lambda ()
(change-directory dir))		  thunk		  (lambda () (change-directory
cwd)))))

HTH


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

* Re: dynamic-wind
  2017-06-30 21:48 ` dynamic-wind Panicz Maciej Godek
@ 2017-07-02  6:00   ` Catonano
  2017-07-02  6:01     ` dynamic-wind Catonano
  2017-07-02 11:58     ` dynamic-wind Chris Vine
  0 siblings, 2 replies; 14+ messages in thread
From: Catonano @ 2017-07-02  6:00 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: guile-user@gnu.org

2017-06-30 23:48 GMT+02:00 Panicz Maciej Godek <godek.maciek@gmail.com>:

>
>
> 2017-06-30 22:33 GMT+02:00 Catonano <catonano@gmail.com>:
>
>> On the irc channel I was suggested that it might have been a good fit for
>> my use case
>>
>> I took a look at it in the manual
>>
>> I'm perplexed. I don't understand it
>>
>> How is it supposed to be used ?
>>
>>
> It's very simple (at least from the point of view of a user)
> When it is tempting to write something like
>
> (define (within-context action)
>   (enter-context)
>   (action)
>   (leave-context))
>
> you simply change it to
>
> (define (within-context action)
>   (dynamic-wind
>     (lambda () (enter-context))
>     action
>     (lambda () (leave-context))))
>
> The thing is, that in general (action) may transfer control outside of the
> scope of that particular context (like, using call/cc or exceptions) -- and
> in such situations, we would like the (leave-context) handler to be
> invoked. If and we ever get back there, we wish that the (enter-context)
> were invoked again.
>
>
>
>> The provided example is somewhat contrived, I couldn't understand it
>> anyway.
>>
>> My use case is basic, really.
>>
>> I have a scheme wrap around a C library for reading xls files, freexl.
>>
>> Freexl uses a pointer to a structure tha represents the opened xls file
>> and
>> its contents
>>
>> Each function writes/reads in the memory region pointed to such pointer.
>>
>> In the end, it requires to use a function that closes the file AND frees
>> all the involved structures in memory.
>>
>> So my idea was that I would have gotten a simple macro, like this
>>
>> (with-xls-file "path/to/my/xls-file.xls" handler-ptr
>>    (do-something handler-ptr)
>>    (do-something-more handler-ptr))
>>
>> and this would have expanded to
>>
>> (freexl-open "path/to/my/xls-file.xls" handler-ptr)
>> (freexl-do-something handler-ptr)
>> (freexl-do-something-more handler-ptr))
>> (freexl-close handler-ptr)
>>
>> Do I need dynamic-wind at all ?
>>
>
> If you don't use dynamic-wind, some of the possible use cases will not be
> covered. Non-local transfers of control will break the system.
>
> I believe you'd like to assume that there shouldn't be any non-local
> transfers of control, but actually you can't know this. And the interface
> to dynamic-wind is very straightforward, so there's no excuse for not using
> it.
>
> Here's a simple real life example in Scheme:
>
> (define current-working-directory getcwd)(define change-directory chdir)
>
> (define (with-changed-working-directory dir thunk)  (let ((cwd (current-working-directory)))    (dynamic-wind (lambda () (change-directory dir))		  thunk		  (lambda () (change-directory cwd)))))
>
> HTH
>
>

aahh I see now

Well. the manual is not clear enough, I think, in this regard

In fact, I think Amirouche got tricked too

When I was playing with his library for accessing a Wiredtiger based db,
there was a bug that when some query went wrong, the connection to the db
didn t get released and so the subsequent connections couldn t be
established

I had to quit Guile and start it again.

I was using

(with-context some-connection
  (query...))


The code for with-context is here (and it doesn t use dynamic-wind as far
as I can see)
https://framagit.org/a-guile-mind/guile-wiredtiger/blob/master/wiredtiger/extra.scm#L328


I think that the use case should be explicitly stated, in the manual, as
you did here

Also the example should be about some db or network connection, not about
call/cc

So that understanding dynamic-wind and its use case wouldn t require
understanding call/cc (which I still don t get)


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

* Re: dynamic-wind
  2017-07-02  6:00   ` dynamic-wind Catonano
@ 2017-07-02  6:01     ` Catonano
  2017-07-02 11:58     ` dynamic-wind Chris Vine
  1 sibling, 0 replies; 14+ messages in thread
From: Catonano @ 2017-07-02  6:01 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: guile-user@gnu.org

Thank you !!


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

* Re: dynamic-wind
  2017-07-02  6:00   ` dynamic-wind Catonano
  2017-07-02  6:01     ` dynamic-wind Catonano
@ 2017-07-02 11:58     ` Chris Vine
  2017-07-05  6:14       ` dynamic-wind Catonano
  1 sibling, 1 reply; 14+ messages in thread
From: Chris Vine @ 2017-07-02 11:58 UTC (permalink / raw)
  To: guile-user

On Sun, 2 Jul 2017 08:00:58 +0200
Catonano <catonano@gmail.com> wrote:
> 2017-06-30 23:48 GMT+02:00 Panicz Maciej Godek
> <godek.maciek@gmail.com>:
> > It's very simple (at least from the point of view of a user)
> > When it is tempting to write something like
> >
> > (define (within-context action)
> >   (enter-context)
> >   (action)
> >   (leave-context))
> >
> > you simply change it to
> >
> > (define (within-context action)
> >   (dynamic-wind
> >     (lambda () (enter-context))
> >     action
> >     (lambda () (leave-context))))
> >
> > The thing is, that in general (action) may transfer control outside
> > of the scope of that particular context (like, using call/cc or
> > exceptions) -- and in such situations, we would like the
> > (leave-context) handler to be invoked. If and we ever get back
> > there, we wish that the (enter-context) were invoked again.
[snip]
> > Here's a simple real life example in Scheme:
> >
> > (define current-working-directory getcwd)(define change-directory
> > chdir)
> >
> > (define (with-changed-working-directory dir thunk)  (let ((cwd
> > (current-working-directory)))    (dynamic-wind (lambda ()
> > (change-directory dir))		  thunk
> > (lambda () (change-directory cwd)))))
> 
> aahh I see now
> 
> Well. the manual is not clear enough, I think, in this regard
[snip]
> I think that the use case should be explicitly stated, in the manual,
> as you did here
> 
> Also the example should be about some db or network connection, not
> about call/cc
> 
> So that understanding dynamic-wind and its use case wouldn t require
> understanding call/cc (which I still don t get)

Possibly the wording of the manual about dynamic-wind at
https://www.gnu.org/software/guile/manual/html_node/Dynamic-Wind.html#Dynamic-Wind
could be improved.  Stating that "If, any time during the execution of
thunk, the dynamic extent of the dynamic-wind expression is escaped
non-locally, out_guard is called" is a somewhat incomplete description
of when the out guard is called, since it is also invoked when the body
of the dynamic wind returns normally.  If you think the wording could
be improved I suggest you file a bug with a suggested wording.  Having
said that, I think that you are getting unnecessarily tied up with
call/cc rather than concentrating on the principle.

dynamic-wind is much more general than just for dealing with database or
network connections, which I think would be a poor focus for the manual.
dynamic-wind is relevant whenever control leaves the dynamic wind block
in question, either normally or by an exception or by invocation of a
specific continuation object such as via call/cc, call/ec or
abort-to-prompt.  Many languages have something similar - it is
analogous in some sense to a C# or Java finally block, which executes
whenever control leaves the associated try block, whether normally or by
virtue of an exception or a return, break, continue or goto statement.

The somewhat more unusual feature of dynamic-wind it that, because
the scheme language permits a dynamic context to be re-entered by the
invocation of a continuation object (say, as obtained by call/cc),
there is also an in guard made available to deal with entry into the
dynamic wind block.

Having said all that, dynamic-wind is not the answer to all cases where
control leaves a block of code non-locally.  It is best suited to cases
where invocation of a continuation object or the raising of an
exception fall to be dealt with in the same way, say by releasing a
resource such as by unlocking a mutex or closing a port.  But that is by
no means always the case - the invocation of a continuation object is
usually a deliberate programmatic strategy, whereas the raising of an
exception is usually not so and instead represents an unexpected
failure event of some kind in the program.

Chris



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

* Re: dynamic-wind
  2017-07-02 11:58     ` dynamic-wind Chris Vine
@ 2017-07-05  6:14       ` Catonano
  2017-07-05  8:23         ` dynamic-wind David Kastrup
  2017-07-08 20:03         ` dynamic-wind Amirouche Boubekki
  0 siblings, 2 replies; 14+ messages in thread
From: Catonano @ 2017-07-05  6:14 UTC (permalink / raw)
  To: Chris Vine; +Cc: guile-user

Chris,

thank you for your remarks.

Yo're right that I was being caught up by continuations AND that I was
probably missing the generality of the concept of dynamic wind

And yet, I still want to clarify my point

My point is not that the manual is incomplete or inaccurate

My point is that the manual does not a good job of _introducing_ people to
the concept of dynamic wind

Especially people wo have not clear in mind a complete map of the use cases
with relative possible solutions.

The manual tends to be a very good reference for already educated people.
But it's not as good in educating people in the first place, in my view.



2017-07-02 13:58 GMT+02:00 Chris Vine <vine35792468@gmail.com>:

> On Sun, 2 Jul 2017 08:00:58 +0200
> > aahh I see now
> >
> dynamic-wind is much more general than just for dealing with database or
> network connections, which I think would be a poor focus for the manual.
>

I was not suggesting to _narrow_ the focus of the manual

I was suggesting to use a more mundane example as an _introduction_ to the
functionality of dynamic wind

The current example could still be given, maybe as the last one

A general principle for the Wikipedia pages is to use an informal
description first and then move on to more formal discssion later in the
page

To allow both audiences (interested in a quick overview and interested in a
deeper analisys) to be served

So I was thinking that the same principle could be used for the discussion
of dynamic wind

I failed to declare this bakthought of mine, though.

That didn't help clarity.

I asked Amirouche his opinion about this threas and e raised several more
points but he also used this sentence (quoing authorized by Amirouche):

"With that thread, I understand the use case of dynamic wind now."

So he wasn't understanding dynamic wind before Panicz's explaination

That seems to confirm my view that the manual is not a great introduction

That said, Amirouche observed that in his Wiredtiger access layer, a state
depending on the db is created and when leaving the dynamic wind context
that sould be unrolled

When reentering it should be properly reproduced

He also considered taht probably in his case, the oprtions of leaving the
context because of an exception and because of an intentional step should
be treated diferently, as you observed


> Having said all that, dynamic-wind is not the answer to all cases where
> control leaves a block of code non-locally.  It is best suited to cases
> where invocation of a continuation object or the raising of an
> exception fall to be dealt with in the same way, say by releasing a
> resource such as by unlocking a mutex or closing a port.  But that is by
> no means always the case - the invocation of a continuation object is
> usually a deliberate programmatic strategy, whereas the raising of an
> exception is usually not so and instead represents an unexpected
> failure event of some kind in the program.


Wrapping up: I concede that dynamic wind is more general than network or
dbs, and that doesn't even exhaust the whole range of possible cases
(thanks !)

But the manual could be improved nonetheless (unless it is meant to NOT be
a tutorial)

One last note: Amirouche lost this thread in his email client and asked me
to post something so he can recuperate this thread and intervene, perhaps


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

* Re: dynamic-wind
  2017-07-05  6:14       ` dynamic-wind Catonano
@ 2017-07-05  8:23         ` David Kastrup
  2017-07-08 20:03         ` dynamic-wind Amirouche Boubekki
  1 sibling, 0 replies; 14+ messages in thread
From: David Kastrup @ 2017-07-05  8:23 UTC (permalink / raw)
  To: guile-user

Catonano <catonano@gmail.com> writes:

> Chris,
>
> thank you for your remarks.
>
> Yo're right that I was being caught up by continuations AND that I was
> probably missing the generality of the concept of dynamic wind
>
> And yet, I still want to clarify my point
>
> My point is not that the manual is incomplete or inaccurate
>
> My point is that the manual does not a good job of _introducing_ people to
> the concept of dynamic wind
>
> Especially people wo have not clear in mind a complete map of the use cases
> with relative possible solutions.
>
> The manual tends to be a very good reference for already educated people.
> But it's not as good in educating people in the first place, in my view.

Arguably the manual example is not done well because it does not cater
for the case that other continuations might get invoked from a different
cwd.  So the cwd should get caught in the entry path of the dynamic-wind
rather than outside, something which I find surprisingly hard to do.
It's also not clear to me what the semantics of delimited continuations
are: for those I don't see a formal reason that there couldn't be
several active at the same time, making resource management via
dynamic-wind even more tricky.

-- 
David Kastrup




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

* Re: dynamic-wind
  2017-07-05  6:14       ` dynamic-wind Catonano
  2017-07-05  8:23         ` dynamic-wind David Kastrup
@ 2017-07-08 20:03         ` Amirouche Boubekki
  2017-07-08 21:34           ` dynamic-wind Marko Rauhamaa
  1 sibling, 1 reply; 14+ messages in thread
From: Amirouche Boubekki @ 2017-07-08 20:03 UTC (permalink / raw)
  To: Catonano, Chris Vine; +Cc: guile-user

Héllo all!

On Wed, Jul 5, 2017 at 8:14 AM Catonano <catonano@gmail.com> wrote:

> My point is that the manual does not a good job of _introducing_ people to
> the concept of dynamic wind
>
> Especially people wo have not clear in mind a complete map of the use cases
> with relative possible solutions.
>
> The manual tends to be a very good reference for already educated people.
> But it's not as good in educating people in the first place, in my view.
>

Maybe you are right. Maybe [0] is missing some more usecases. I consider
dynamic-wind an advanced concept not required for usual hacking. It's like
"if you don't know what you are doing, don't use it"

[0]
https://www.gnu.org/software/guile/manual/html_node/Dynamic-Wind.html#Dynamic-Wind



2017-07-02 13:58 GMT+02:00 Chris Vine <vine35792468@gmail.com>:
>
> > On Sun, 2 Jul 2017 08:00:58 +0200
> > > aahh I see now
> > >
> > dynamic-wind is much more general than just for dealing with database or
> > network connections, which I think would be a poor focus for the manual.
> >
>
> I was not suggesting to _narrow_ the focus of the manual
>
> I was suggesting to use a more mundane example as an _introduction_ to the
> functionality of dynamic wind
>
> The current example could still be given, maybe as the last one
>
> A general principle for the Wikipedia pages is to use an informal
> description first and then move on to more formal discssion later in the
> page
>
> To allow both audiences (interested in a quick overview and interested in a
> deeper analisys) to be served
>
> So I was thinking that the same principle could be used for the discussion
> of dynamic wind
>

I agree with you. A small introduction and a deeper look should both make
up the manual for each entry. That's said, the current page does in fact
have an introduction but starts with some C stuff which I don't understand,
which is why I prolly only skimmed over it the first time. Also the whole
article only cite call/cc in the example. My understanding now is that
dynamic-wind is only useful if you do use call/cc or one of its surrogate.
So call/cc should appear be in the introduction paragraph.


> That seems to confirm my view that the manual is not a great introduction
>

You are prolly more informed than me. I learned scheme from r7rs small
paper [1] and I use the manual mainly as a reference.

[1] http://trac.sacrideo.us/wg/raw-attachment/wiki/WikiStart/r7rs.pdf


>
> That said, Amirouche observed that in his Wiredtiger access layer, a state
> depending on the db is created and when leaving the dynamic wind context
> that sould be unrolled
>
> When reentering it should be properly reproduced
>
> He also considered taht probably in his case, the oprtions of leaving the
> context because of an exception and because of an intentional step should
> be treated diferently, as you observed
>

Indeed, in wiredtiger the with-context procedure which is not perfect, but
still does the job is implemented as follow:

(define-syntax-rule (with-context env body ...)
  (let ((env* env))
    ;; get or create a context and set it as current *context* value
    (let ((context (get-or-create-context env*)))
      (with-fluids ((*context* context))
        ;; execute the body
        (call-with-values
          (lambda () (begin body ...))
          (lambda out
            ;; push back the context to the context pool
            (with-mutex (env-mutex env*)
              (env-contexts! env* (cons context (env-contexts env*))))
            (apply values out)))))))

(define-syntax-rule (with-context* body ...)
  (let ((env (fluid-ref *env*)))
    (with-context env body ...)))

(define-syntax-rule (with-env env body ...)
  (let ((env* env))
    (with-fluids ((*env* env*))
      (call-with-values
        (lambda () (with-context* body ...))
        (lambda out
          (env-close env*)
          (apply values out))))))

It's inspired from ports procedures [2]. Like it tried to explain to
Catonano it's wrong to say that all with-fu procedure must be written using
dynamic wind. A proof of that is the port procedures in [2]. In fact, if
you can't re-compute the state before the dynamic context is escaped,
dynmaic wind is useless, which is the case of wiredtiger's with-context.

[2] http://git.savannah.gnu.org/cgit/guile.git/tree/module/ice-9/ports.scm


>
>
> > Having said all that, dynamic-wind is not the answer to all cases where
> > control leaves a block of code non-locally.  It is best suited to cases
> > where invocation of a continuation object or the raising of an
> > exception fall to be dealt with in the same way, say by releasing a
> > resource such as by unlocking a mutex or closing a port.  But that is by
> > no means always the case - the invocation of a continuation object is
> > usually a deliberate programmatic strategy, whereas the raising of an
> > exception is usually not so and instead represents an unexpected
> > failure event of some kind in the program.
>
>
> Wrapping up: I concede that dynamic wind is more general than network or
> dbs, and that doesn't even exhaust the whole range of possible cases
> (thanks !)
>
> But the manual could be improved nonetheless (unless it is meant to NOT be
> a tutorial)
>
> One last note: Amirouche lost this thread in his email client and asked me
> to post something so he can recuperate this thread and intervene, perhaps
>

I figured I have a backup solution in my gmail account...


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

* Re: dynamic-wind
  2017-07-08 20:03         ` dynamic-wind Amirouche Boubekki
@ 2017-07-08 21:34           ` Marko Rauhamaa
  2017-07-09  7:21             ` dynamic-wind David Kastrup
  0 siblings, 1 reply; 14+ messages in thread
From: Marko Rauhamaa @ 2017-07-08 21:34 UTC (permalink / raw)
  To: Amirouche Boubekki; +Cc: guile-user

Amirouche Boubekki <amirouche.boubekki@gmail.com>:

> I consider dynamic-wind an advanced concept not required for usual
> hacking.

Hm. Python's try/finally has several uses in virtually every program.

Trouble is, Scheme's continuations make it impossible to know when
something is really final. In fact, implementing coroutines and
cooperative multitasking using continuations almost guarantee a repeated
back-and-forth through dynamic-wind.

I strongly suspect Scheme's continuations are more trouble than they are
worth.


Marko



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

* Re: dynamic-wind
  2017-07-08 21:34           ` dynamic-wind Marko Rauhamaa
@ 2017-07-09  7:21             ` David Kastrup
  0 siblings, 0 replies; 14+ messages in thread
From: David Kastrup @ 2017-07-09  7:21 UTC (permalink / raw)
  To: guile-user

Marko Rauhamaa <marko@pacujo.net> writes:

> Amirouche Boubekki <amirouche.boubekki@gmail.com>:
>
>> I consider dynamic-wind an advanced concept not required for usual
>> hacking.
>
> Hm. Python's try/finally has several uses in virtually every program.
>
> Trouble is, Scheme's continuations make it impossible to know when
> something is really final.

When there is no reference to it anymore, just like with memory
allocation.

> In fact, implementing coroutines and cooperative multitasking using
> continuations almost guarantee a repeated back-and-forth through
> dynamic-wind.
>
> I strongly suspect Scheme's continuations are more trouble than they
> are worth.

Depends on your architecture.  The basic idea is not to have different
memory allocation for heap and return stack.  Basically, you put your
return "stack" in the heap and never actually reclaim memory when
returning but only when garbage collecting.

When function calls are hardware-supported but garbage-collection isn't,
the trade-offs for that model are not exactly fabulous.

Now continuations are not actually pervasively used in Scheme
programming like garbage-collection data life times are, and their
actual use does not tie greatly into Scheme's call syntax.  Yet a lot of
core Scheme constructs have constraints on their implementation because
the standards prescribe semantics compatible with pervasive use of
continuations.

So for real-life implementations of Scheme on today's architectures,
I find the cost/benefit tradeoff of continuations in relation to the
programming language unconvincing.

This might change in future architectures: remember that in Fortran's
heydays, stuff like stack-local variables and addressing and recursion
came with heavy associated costs because the computer architectures were
not actually designed to do complex things like stack-relative
addressing (anybody remember COMPASS' RJI, return jump instruction, for
function calls?).

So it's conceivable that garbage collection will become more native
(which would also help the data handling speed of any sweeped
garbage-collecting language, and there are numerous of them by now) and
that procedure handling might be made more compatible with it
eventually.

It's probably worth mentioning that "ChickenScheme" does this sort of
garbage-collection on the stack without actually executing function
returns in C.

-- 
David Kastrup




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

* Re: dynamic-wind
@ 2017-07-09 12:59 Chris Vine
  2017-07-09 14:09 ` dynamic-wind Vítor De Araújo
  0 siblings, 1 reply; 14+ messages in thread
From: Chris Vine @ 2017-07-09 12:59 UTC (permalink / raw)
  To: guile-user

On Sun, 09 Jul 2017 00:34:13 +0300
Marko Rauhamaa <marko@pacujo.net> writes:
> Hm. Python's try/finally has several uses in virtually every
> program.
>
> Trouble is, Scheme's continuations make it impossible to know when
> something is really final.  
> 
> In fact, implementing coroutines and cooperative multitasking using
> continuations almost guarantee a repeated back-and-forth through
> dynamic-wind.
>
> I strongly suspect Scheme's continuations are more trouble than they
> are worth.  

I disagree with that.  On the first point, you know that a
dynamic-wind block can no longer be re-entered (if that is what you mean
by "really final") when the continuation object concerned is no longer
accessible.  At that point it, and all references to other objects
encapsulated by the continuation, will be released in the ordinary
way.  You also know the same when your continuation is only an escape
continuation.

Secondly, this is something of an irrelevance.  I have found it very
rare that one would want to use dynamic-wind when implementing
co-operative multi-tasking with coroutines (at any rate,
https://github.com/ChrisVine/guile-a-sync only does so for thread pool
thread counts, and that is to cater for exceptions in local code rather
than for jumps via continuation objects).  Jumping out of a
dynamic-wind block using a coroutine is generally inimical to the kind
of asynchronous programming that coroutines are used for: you generally
don't want to unset the state of the continuation, and then set it up
again when you re-enter.  You normally want to leave it just as it was
at the time you yielded.

I may be mistaking you for another poster, but I think you have
previously said that you prefer the inversion of control ("callback
hell") style of asynchronous programming to using coroutines.  You
would not usually think of using dynamic-wind there either, I hope.

Scheme's continuations are very useful.  Guile's delimited
continuations are even more so.  Dynamic-wind not so much, because it
is a very blunt instrument.

Chris



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

* Re: dynamic-wind
  2017-07-09 12:59 dynamic-wind Chris Vine
@ 2017-07-09 14:09 ` Vítor De Araújo
  2017-07-09 14:49   ` dynamic-wind Chris Vine
  0 siblings, 1 reply; 14+ messages in thread
From: Vítor De Araújo @ 2017-07-09 14:09 UTC (permalink / raw)
  To: guile-user

On 09/07/2017 09:59, Chris Vine wrote:
> On Sun, 09 Jul 2017 00:34:13 +0300
> Marko Rauhamaa <marko@pacujo.net> writes:
>> Hm. Python's try/finally has several uses in virtually every
>> program.
>>
>> Trouble is, Scheme's continuations make it impossible to know when
>> something is really final.  
>>
>> In fact, implementing coroutines and cooperative multitasking using
>> continuations almost guarantee a repeated back-and-forth through
>> dynamic-wind.
>>
>> I strongly suspect Scheme's continuations are more trouble than they
>> are worth.  
> 
> I disagree with that.  On the first point, you know that a
> dynamic-wind block can no longer be re-entered (if that is what you mean
> by "really final") when the continuation object concerned is no longer
> accessible.  At that point it, and all references to other objects
> encapsulated by the continuation, will be released in the ordinary
> way.  You also know the same when your continuation is only an escape
> continuation.

That helps the implementation know if a continuation will not be entered
again, but it does not help when you want to do the kinds of things you
do with unwind-protect or try/finally in other languages. For example,
with unwind-protect, you can open a port or another resource and ensure
it will be closed if control escapes the unwind-protect form. You can do
that with dynamic-wind, but it is less meaningful to do so because
control can be re-entered again. There is no language construct (as far
as I know – maybe there is in Guile) that can detect that flow has
exited the form and *will never enter it again*. So the presence of
continuations make operations like unwind-protect less meaningful. I
don't know what is the Scheme way to address these situations.

> Secondly, this is something of an irrelevance.  I have found it very
> rare that one would want to use dynamic-wind when implementing
> co-operative multi-tasking with coroutines (at any rate,
> https://github.com/ChrisVine/guile-a-sync only does so for thread pool
> thread counts, and that is to cater for exceptions in local code rather
> than for jumps via continuation objects).  Jumping out of a
> dynamic-wind block using a coroutine is generally inimical to the kind
> of asynchronous programming that coroutines are used for: you generally
> don't want to unset the state of the continuation, and then set it up
> again when you re-enter.  You normally want to leave it just as it was
> at the time you yielded.
> 
> I may be mistaking you for another poster, but I think you have
> previously said that you prefer the inversion of control ("callback
> hell") style of asynchronous programming to using coroutines.  You
> would not usually think of using dynamic-wind there either, I hope.
> 
> Scheme's continuations are very useful.  Guile's delimited
> continuations are even more so.  Dynamic-wind not so much, because it
> is a very blunt instrument.
> 
> Chris
> 

-- 
Vítor De Araújo
https://elmord.org/



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

* Re: dynamic-wind
  2017-07-09 14:09 ` dynamic-wind Vítor De Araújo
@ 2017-07-09 14:49   ` Chris Vine
  2017-07-17 10:04     ` dynamic-wind Catonano
  0 siblings, 1 reply; 14+ messages in thread
From: Chris Vine @ 2017-07-09 14:49 UTC (permalink / raw)
  To: guile-user

On Sun, 9 Jul 2017 11:09:25 -0300
Vítor De Araújo <vbuaraujo@sapo.pt> wrote:
> On 09/07/2017 09:59, Chris Vine wrote:
> > On Sun, 09 Jul 2017 00:34:13 +0300
> > Marko Rauhamaa <marko@pacujo.net> writes:  
> >> Hm. Python's try/finally has several uses in virtually every
> >> program.
> >>
> >> Trouble is, Scheme's continuations make it impossible to know when
> >> something is really final.  
> >>
> >> In fact, implementing coroutines and cooperative multitasking using
> >> continuations almost guarantee a repeated back-and-forth through
> >> dynamic-wind.
> >>
> >> I strongly suspect Scheme's continuations are more trouble than
> >> they are worth.    
> > 
> > I disagree with that.  On the first point, you know that a
> > dynamic-wind block can no longer be re-entered (if that is what you
> > mean by "really final") when the continuation object concerned is
> > no longer accessible.  At that point it, and all references to
> > other objects encapsulated by the continuation, will be released in
> > the ordinary way.  You also know the same when your continuation is
> > only an escape continuation.  
> 
> That helps the implementation know if a continuation will not be
> entered again, but it does not help when you want to do the kinds of
> things you do with unwind-protect or try/finally in other languages.
> For example, with unwind-protect, you can open a port or another
> resource and ensure it will be closed if control escapes the
> unwind-protect form. You can do that with dynamic-wind, but it is
> less meaningful to do so because control can be re-entered again.
> There is no language construct (as far as I know – maybe there is in
> Guile) that can detect that flow has exited the form and *will never
> enter it again*. So the presence of continuations make operations
> like unwind-protect less meaningful. I don't know what is the Scheme
> way to address these situations.

unwind-protect is a dynamic-wind without the in guard.

The scheme way of dealing with re-entry (which is not possible in
common lisp) is to initialize in the in guard the resources to be
released in the out guard.  There are two problems: first it may be you
cannot do that - you may need to initialize the resources elsewhere and
it may not be meaningful anyway to re-initialize them - see below.
Secondly there is no uncomplicated way of distinguishing between
non-local exit on invocation of a continuation object, non-local exit
on the throwing of an exception and a normal exit, but the required
treatment may be different in each case.  Obviously you can distinguish
using flags and so forth, but it is a pain.

There is a language construct in guile for knowing whether a
continuation object is a full continuation or an escape continuation:
call/cc produces full continuations and call/ec produces escape
continuations (which cannot be re-entered).  call-with-prompt produces
re-enterable delimited continuations.

As I said, dynamic-wind is a very blunt instrument.  I find it useful
only for very local resources of a particular kind.  Releasing a mutex
is a common case where dynamic-winds are useful (guile has the
with-mutex form).  Ports, as in your example, are not as clear cut.
Sure, you may want to close the port when you exit a particular block
in the case of a normal exit, an exception or an escape continuation,
but do you necessarily want to do so if you might re-enter later and
closing the port is a destructive operation (it vacates input buffers)?



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

* Re: dynamic-wind
  2017-07-09 14:49   ` dynamic-wind Chris Vine
@ 2017-07-17 10:04     ` Catonano
  0 siblings, 0 replies; 14+ messages in thread
From: Catonano @ 2017-07-17 10:04 UTC (permalink / raw)
  To: Chris Vine; +Cc: guile-user

I'm so glad for all the people who intervened in this discussion

As this made the subtleties of the issue clearer.


Thank you people !

2017-07-09 16:49 GMT+02:00 Chris Vine <vine35792468@gmail.com>:

> On Sun, 9 Jul 2017 11:09:25 -0300
> Vítor De Araújo <vbuaraujo@sapo.pt> wrote:
>
> unwind-protect is a dynamic-wind without the in guard.
>
>
>
[...]


> As I said, dynamic-wind is a very blunt instrument.  I find it useful
> only for very local resources of a particular kind.  Releasing a mutex
> is a common case where dynamic-winds are useful (guile has the
> with-mutex form).  Ports, as in your example, are not as clear cut.
> Sure, you may want to close the port when you exit a particular block
> in the case of a normal exit, an exception or an escape continuation,
> but do you necessarily want to do so if you might re-enter later and
> closing the port is a destructive operation (it vacates input buffers)?
>
>
In my particular case, I think that abruptly closing the file and then
reopening it would be an acceptable trade off

Freexl functions return error codes when problems arise and those could
help the user in assessing the problem

xls files can be corrupted as different versions of Office can save them in
inconsistent states and there's only so much my library can do

Thank you again, people


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

end of thread, other threads:[~2017-07-17 10:04 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-30 20:33 dynamic-wind Catonano
2017-06-30 21:48 ` dynamic-wind Panicz Maciej Godek
2017-07-02  6:00   ` dynamic-wind Catonano
2017-07-02  6:01     ` dynamic-wind Catonano
2017-07-02 11:58     ` dynamic-wind Chris Vine
2017-07-05  6:14       ` dynamic-wind Catonano
2017-07-05  8:23         ` dynamic-wind David Kastrup
2017-07-08 20:03         ` dynamic-wind Amirouche Boubekki
2017-07-08 21:34           ` dynamic-wind Marko Rauhamaa
2017-07-09  7:21             ` dynamic-wind David Kastrup
  -- strict thread matches above, loose matches on Subject: below --
2017-07-09 12:59 dynamic-wind Chris Vine
2017-07-09 14:09 ` dynamic-wind Vítor De Araújo
2017-07-09 14:49   ` dynamic-wind Chris Vine
2017-07-17 10:04     ` dynamic-wind Catonano

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