Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.postscript > #3125

Re: Control Structures

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>

Show all headers | View raw


[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


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