DEV Community

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

Posted on

4 1

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

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay