Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.postscript > #3125
| From | Carlos <carlos@cvkm.cz> |
|---|---|
| Newsgroups | comp.lang.postscript |
| Subject | Re: Control Structures |
| Date | 2017-06-23 00:28 +0200 |
| Organization | A noiseless patient Spider |
| Message-ID | <20170623002801.61560cd4@samara.DOMA> (permalink) |
| References | <2f65c3d3-60f0-48d6-af25-7af2964b9254@googlegroups.com> |
[luser droog <luser.droog@gmail.com>, 2017-06-21 22:50]
> In the midst of the coding for the Parser Combinators, I think
> I've come up with a nice way to implement functions that behave
> like control structures. Notwithstanding potential problems
> with redefinition of needed operators which Carlos' map function
> solves, this way provides fairly readable control structures
> with nice features.
>
> Starting with curry and compose we get a pretty readable
> definition for adding local variables to functions. This is a
> recapitulation of the code from the thread "func def".
>
>
>
> /curry { /exec cvx 3 array astore cvx } def
> /combine { /exec cvx exch 1 index 4 array astore cvx } de
> /reverse-array { [ exch dup length 1 sub -1 0 { 2 copy get 3 1 roll pop } for
> pop ] } def /args { dup length dict begin {exch def} forall } def
> /func { exch reverse-array //args curry exch combine {end} combine } def
> %/f {x y z}{ x y add z mul } func def 1 2 3 f = %=> 9
>
>
> Then we can write a new control structure by adding code
> to an existing control structure. The one I keep writing
> lately is /fortuple which calls the proc with slices of
> the array (or string) instead of the elements. As a nice
> side-effect, if you use an empty proc {} it just slices
> up the array (or string).
>
> /fortuple {arr n proc}{
> ({
> 0 //n //arr length 1 sub {
> //arr exch //n getinterval
> //proc exec
> } for
> }) cvx exec exec
> } func def
>
> The 'cvx' makes the string executable. Calling 'exec' on
> that yields the executable procedure scanned from the
> string with all //immediate names loaded at that point.
> Then one more 'exec' to execute the procedure.
>
> The advantage is the execution can be made invisible to
> the /proc. By defining the currentdict as /mydict and
> sandwiching the '//proc exec' with 'end ... //mydict begin'
> the /proc will see none of our bookkeeping either on
> the stack or the dict stack.
>
> /fortuple {arr n proc}{
> /mydict currentdict def
> ({
> 0 //n //arr length 1 sub {
> //arr exch //n getinterval
> end
> //proc exec
> //mydict begin
> } for
> }) cvx exec exec
> } func def
I love how simple and understandable it is. I still don't like parsing the
string every time, though. I know it's an irrational dislike, it's probably even
faster than replacing the "variables" by hand, but...
It's also more cumbersome to edit :)
> The final complication arises if the /proc wants to call
> 'exit' to terminate the loop early. We're mostly set up
> to handle this. The looping happens inside a single
> built-in looping construct, 'for'. So 'exit' will exit
> this single loop. Unfortunately this bypasses the
> '//mydict begin' that we need since the 'func' wrapper
> adds an 'end' to the end of the function.
Start the string with "({ end " and finish it with " } for //mydict begin })"?
>
> /fortuple {arr n proc}{
> /mydict currentdict def
> ({
> 0 //n //arr length 1 sub {
> {
> //arr exch //n getinterval
> end
> //proc exec
> //mydict begin
> } stopped {
> $error /errorname get /invalidexit eq
> { 1 dict begin exit }{ stop } ifelse
> } if
> } for
> }) cvx exec exec
> } func def
>
>
> This last ugly step is the next hurdle I think.
> It would be nice to tuck this part under the rug somehow
> and make it look more like the first or second version.
> A variation of 'func' which did not append an 'end' would
> allow us to remove the /mydict stuff since we could put
> 'end' before the final 'exec' and remove the dict early.
> That would work since all the variables are instantiated
> in the generated procedure and the /dict is no longer
> necessary.
>
> This version requires that the array (or string) length
> be divisible by n. A different version from here,
> https://stackoverflow.com/documentation/postscript/6199/error-handling/21486/re-throwing-errors#t=201706220535518165373
> delivers any smaller remainder as a last iteration.
> That version was written before I realized how nice the
> '({...}) cvx exec exec' construct was. The 'cvx exec'
> could also be written 'token pop exch pop' which will
> do the same thing. But 'cvx exec' is shorter.
>
> % alternate version
>
> % array n proc . -
> % Like `forall` but delivers length=n subsequences produced by getinterval
> /fortuple { 4 dict begin
> 0 {offset proc n arr} {exch def} forall
> /arr load length n idiv
> {
> {
> /arr load offset n getinterval
> [ /proc load currentdict end /begin cvx ] cvx exec
> /offset offset n add def
> } stopped {
> $error /errorname get /invalidexit eq
> { 1 dict begin exit }{ stop } ifelse
> } if
> } repeat
> end
> } def
>
> %[ 0 1 10 {} for ] 3 {} fortuple pstack clear ()=
Back to comp.lang.postscript | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
Control Structures luser droog <luser.droog@gmail.com> - 2017-06-21 22:50 -0700
Re: Control Structures Carlos <carlos@cvkm.cz> - 2017-06-23 00:28 +0200
Re: Control Structures luser droog <luser.droog@gmail.com> - 2017-06-23 00:01 -0700
Re: Control Structures luser droog <luser.droog@gmail.com> - 2017-06-28 10:57 -0700
Re: Control Structures luser droog <luser.droog@gmail.com> - 2017-06-28 21:25 -0700
Re: Control Structures luser droog <luser.droog@gmail.com> - 2017-06-30 03:05 -0700
Re: Control Structures (Ordered Dictionaries) luser droog <luser.droog@gmail.com> - 2017-07-03 20:01 -0700
Binding - Re: Control Structures (Ordered Dictionaries) Carlos <carlos@cvkm.cz> - 2017-07-04 17:21 +0200
Type-checked function arguments - Re: Binding - Re: Control Structures (Ordered Dictionaries) luser droog <luser.droog@gmail.com> - 2017-07-09 10:44 -0700
Re: Type-checked function arguments - Re: Binding - Re: Control Structures (Ordered Dictionaries) luser droog <luser.droog@gmail.com> - 2017-07-10 09:33 -0700
Re: Type-checked function arguments - Re: Binding - Re: Control Structures (Ordered Dictionaries) luser droog <luser.droog@gmail.com> - 2017-07-15 20:00 -0700
Re: Type-checked function arguments - Re: Binding - Re: Control Structures (Ordered Dictionaries) luser droog <luser.droog@gmail.com> - 2017-07-25 23:07 -0700
Re: Type-checked function arguments - Re: Binding - Re: Control Structures (Ordered Dictionaries) Carlos <carlos@cvkm.cz> - 2017-07-26 16:41 +0200
Re: Type-checked function arguments - Re: Binding - Re: Control Structures (Ordered Dictionaries) luser droog <luser.droog@gmail.com> - 2017-07-26 10:29 -0700
csiph-web