Alternative topological sorting implementation
Maxime Devos
(13 Apr 2023 15:12 UTC)
|
Re: Alternative topological sorting implementation
Marc Nieper-Wißkirchen
(13 Apr 2023 15:29 UTC)
|
Re: Alternative topological sorting implementation
Maxime Devos
(13 Apr 2023 16:00 UTC)
|
Re: Alternative topological sorting implementation
Marc Nieper-Wißkirchen
(13 Apr 2023 20:18 UTC)
|
Re: Alternative topological sorting implementation
Marc Nieper-Wißkirchen
(13 Apr 2023 20:35 UTC)
|
Re: Alternative topological sorting implementation
Maxime Devos
(17 Apr 2023 21:33 UTC)
|
Re: Alternative topological sorting implementation
Marc Nieper-Wißkirchen
(18 Apr 2023 05:58 UTC)
|
Re: Alternative topological sorting implementation Maxime Devos (18 Apr 2023 07:53 UTC)
|
Re: Alternative topological sorting implementation
Maxime Devos
(17 Apr 2023 21:13 UTC)
|
Op 18-04-2023 om 07:57 schreef Marc Nieper-Wißkirchen: > Am Mo., 17. Apr. 2023 um 23:32 Uhr schrieb Maxime Devos > <xxxxxx@telenet.be>: >> >> >> >> Op 13-04-2023 om 22:34 schreef Marc Nieper-Wißkirchen: >>> PPS Maybe I should have better pointed to what I called liquids here: >>> https://github.com/mnieper/scheme-libraries#liquids. Although one can >>> change them with set!, there is no mutation of a location in the store >>> happening, > but just some delimited continuation wizardy. The thing I >>> like about liquids is that they abstract away from the rather >>> low-level continuation primitives. >> > >>> So you can just set! visiting and set! visited and are still doing >>> pure programming. :) Liquids can be easily implemented in Guile. Do >>> you think they would make a good addition? >> >> AFAICT, these are just parameter objects, except for 'change them with >> liquid-set!, but purely!'. I haven't ever seen a use of doing a >> mutation of a parameter that couldn't be improved by doing a >> 'parameterize' (cf. let-liquid') (or not using parameters at all) instead. > > Replacing the mutation of a parameter (which has indefinite extent) > with parameterize (which has dynamic extent) is generally not possible I am not talking about whether something it's possible in general, I am only taking about situations encountered in practice. > without a non-local program transformation (which may not be > possible). Well, yes, sometimes to improve a program, you need to do some non-local transformation. It's also called "code refactoring" sometimes. I don't see an issue here. And yes, sometimes you can't replace parameter mutation by parameterize, but there exist other replacements too; there is more to Scheme than only parameters. > As an example, consider you have a for-each (higher-order) > procedure modeling some sequence and want to return a fold procedure > for it. You would have to use the liquids' set! for it. No. As I understand it, this 'for-each -> fold' transformation only uses liquid-set!, not let-liquid -- it only uses mutation of liquids, not parametrize of liquids. As such, this transformation only needs a pure implementation of a SRFI-111 box, perhaps the state implementation at <https://github.com/mnieper/scheme-libraries/blob/9f5d134b5ff487244c9b9a1d983ce2d97a797851/test-effect.scm#L50>. This transformation could then be improved by using the easier to understand 'state' instead of the more powerful and more complicated 'liquids'. That said, I only know how to implement 'map' in terms of 'for-each'; 'fold' is something I haven't tried before to implement simultaneously imperatively and purely; perhaps the equivalent of SRFI-111 boxes is insufficient. >> As such, I would answer your question with 'no'. (Of course, perhaps >> there is some application where mutating a parameter would be a really >> good fit instead.) >> >> Even then, I disagree with "and are still doing pure programming." -- if >> you implement a pure implementation (e.g. in Scheme without set! stuff) >> of an impure language (e.g. Scheme with set! stuff), and then use your >> pure implementation to the impure language, then you're doing impure >> programming -- it's the language that matters, not the implementation of >> the language (*). > > I get your point, but liquids don't reimplement Scheme's `set!`. > Scheme's `set!' modifies locations in the store (of the formal > semantics of Scheme), and this modification can be observed. This is > not true for the liquid-version of `set!'. The liquid-version implement its own equivalent of the store, and you sure can observe mutations of that: (stuff to install liquid effect stuff ;; I'm using the parameter API instead of the liquid API ;; because that's what I'm familiar here. (let ((p (make-parameter 'old))) (p 'stuff) ; also, here we use the liquid reimplementation of 'set!' (observe (p)))) ; 'stuff is observed, not 'old'! That this store is not ‘on the same level’ (so to say) as the store described in the Scheme specifications, and that locations (i.e. liquids) + mutations (i.e. liquid-set!) are implemented in a pure manner by the effect handler is irrelevant: ‘it's the language that matters, not the implementation of the language’ -- from the POV of the stuff inside the effect handler, the store and kind of locations that matters is the store implemented by liquid-set!, not the store implemented by the Scheme implementation (e.g. Racket, Guile, ...) itself. > Of course, one has to > agree upon what one means by purity (where there is no absolute > definition). The definition I use here is exactly about whether > previously allocated locations in the store are modified (and so that > this mutation is observable). For the relevant store, yes. If mutation is unobservable, then it's useless -- the point of mutation is being observable; if mutation is unobservable, you could just not mutate instead. >> (*) There might be some exceptions like if e.g. you use the purity of >> the host language to implement, say, time travel, for the implemented >> impure language, but usually I find the "but the mutation is implemented >> purely!!!" a pointless distinction (except for neatness points). > > You can employ a much stricter definition of purity (let us call it > "strict-purity") for now. Neither the liquid version of `set!', nor > the use of parameters (even without mutating them), nor the use > (delimited) continuation, nor the procedure `cons' are strictly pure. > In particular, your solution of the topological sort is also not > strictly pure. > > For many reasonings, this strict pureness is not helpful, though. See > my for-each/fold example from above, where you need pureness in the > first sense but where questions of strict pureness are not helpful. Well, yes, it's not helpful. That's why I'm not using that notion. My personal definition: 'pure = no mutation, and it doesn't matter how 'purely' you implement mutation' (I know there exist other stricter definitions like "no effects"). And yes, then my implementation isn't pure, but as I wrote before: ‘and I wanted to avoid 'set!', but perhaps I'm just implementing 'set!' in terms of delimited continuations here.’ I never claimed that my implementation is pure. (I also never claimed that purity is required or always a good thing TBC.) Greetings, Maxime.