wryun / es-shell

es: a shell with higher-order functions
http://wryun.github.io/es-shell/
Other
313 stars 26 forks source link

Manipulating code blocks #30

Closed simalaia closed 2 years ago

simalaia commented 3 years ago

Is it possible to treat code blocks as structures and manipulate them as such? I'm poking at implementing something like the multipipe blocks from dagsh and figured a basic version could be doable with a function that takes a block and just rewires the pipes.

wryun commented 3 years ago

I believe - and take this with a grain of salt, because I'm not an expert - that there's no clean way to get at this (unless you want to mess with strings). Read the section on 'Program Fragments', noting particularly the equivalence with word and 'is treated as an indivisible unit'.

This might clarify:

; x = { ls | head }
; echo $x
{%pipe {ls} 1 0 {head}}
; echo $x(1)
{%pipe {ls} 1 0 {head}}

Here you notice the way es internally rewrites pipes into 'normal' es calls (where the first thing is executed and each part is another program fragment), but also that you can't index into a fragment (here it's a single element list).

On Thu, 25 Feb 2021 at 18:18, simalaia notifications@github.com wrote:

Is it possible to treat code blocks as structures and manipulate them as such? I'm poking at implementing something like the multipipe blocks from dagsh and figured a basic version could be doable with a function that takes a block and just rewires the pipes.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/wryun/es-shell/issues/30, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAT4YZT5QXYDSDAHLVAID3TAX2VNANCNFSM4YF6WIEQ .

simalaia commented 3 years ago

Ah, in my enthusiasm I read that section and only noted that program fragments are effectively first class and completely ignored the 'indivisible' part... One could maybe do this in a slightly more heavy handed way:

; fn f { echo $*(1) }
; f ls head
ls

I'll toy around with this and see whether I can come up with anything.

Somewhat unrelated, are there any structures in es other than that one dimensional lists? Just asking in case I overlooked that too.

mwgamera commented 3 years ago

While program fragments can't be manipulated in any other way than executing or stringifying them, you have a lot of ways to influence their behavior on execution. You can, for example, redefine those %pipe and %seq hooks and make them do something completely different.

As for the structures, there are only flat lists, ...and closures, so you can make an arbitrarily complex structures you need. :wink: (Be careful, however, about what's stringified and exported to environment.)

fn cons c {result @{result $c($1)}}
fn car {$1 1}
fn cdr {$1 2}

x = <={(cons <={cons foo bar}
             <={cons baz quux})}

echo <={cdr <={car $x}}  # ==> bar

# or even...

let (orig-pathsearch = $fn-%pathsearch;
  fn-compose = @ a b{result @{$a <={$b $*}}})
fn %pathsearch {
  let (a=$1; b=; f=$&result)
  forever {
    (a b) = <={~~ $a c*[ad]r}
    if {~ $b ()} {return <={$orig-pathsearch $*}}
    f = <={compose c$b^r $f}
    if {~ $a ''} {return $f}
    a = c$a^r
  }
}

echo <={cadr $x}  # ==> baz
simalaia commented 3 years ago

Oh, good point! I was inventing complicated schemes involving building structures on tmpfs... This is much simpler thanks. :)