DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Playing around with Elvish, a new(ish) shell
Daniel Fitzpatrick
Daniel Fitzpatrick

Posted on

Playing around with Elvish, a new(ish) shell

1

Discovering Elvish

Last year the youtube algorithm suggested I watch this video, a brief explanation of the vision behind a new shell. The video itself was a few years old, so I was pleased to discover a busy Github repo and active community. I installed elvish and went about my business, pridefully thinking that my familiarity with bash would act as a stalwart defense against any noob mistakes. A couple of noob mistakes made in quick succession convinced me I had better read the docs anyway.

This wasn't as bad as expected. The Elvish docs were expertly organized and easy to read. For maybe the first time ever I felt inspired to write a decent amount of code in a shell scripting language.

Elvish offers first-class support for a number of features that are interesting to find in a shell scripting language, but they are seamlessly integrated and never feel out of place.

  • lexical scopes
  • types/kinds
  • sensible math operators
  • proper function signature with var-args
  • plus optional named params with default values
  • higher-level functions
  • persistent, immutable lists & maps
  • parallel execution
  • namespaces
  • package manager!!!
  • so much more...

One feature I have not yet taken advantage of in my own projects are the styling builtins. I am eager to see how they simplify some extant parts of my project.

Goofing around

The first thing I did was to implement some of the core library functions from Clojure. 2

fn partial [f @supplied]{
  put [@args]{ 
    @args = (base:check-pipe $args)
    $f $@supplied $@args 
  }
}

fn juxt [@fns]{
  put [@args]{
    @args = (base:check-pipe $args)
    for f $fns {
      $f $@args
    }
  }
}

fn reduce [f acc @arr]{
  for a $arr {
    acc = ($f $acc $a)
  }
  put $acc
}

This gives you currying, juxtaposition, and (ofc) folding.

# all of this available in the 'fun' and 'base' namespaces
# except in the float64 type signature, '()' is output capture in elvish eg '$()' or '``'
# $<fn>~ is a function handle/reference

~> (fun:juxt $base:dec~ $base:inc~) 10
(float64 9)
(float64 11)

~> (fun:partial $+~ 2) 10
(float64 12)

~> fun:reduce $+~ (range 10)
(float64 45)

In the next entry I may write about my approach to lazy iterators(!!) in Elvish, or how seamless the Elvish package manager has made the development process.


  1. Cover image made by Matty Rodgers - unfinished piece entered in a competition. ↩

  2. I eventually wrote a great deal of them here. ↩

Latest comments (0)

Hi!I'm Noah!

Hey, my name is Noah and I’m the one who set up this ad!


My job is to get you to join DEV, so if you fancy doing me a favor, I’d love for you to create an account.
Β 
If you found DEV from searching around, here are a couple of our most popular articles on DEV: