I decided to give the elvish shell a try today. Elvish is a shell written in golang, designed to be more expressive than bash.
Bash drops just short of being a programming language. For example, it doesn’t do floating point arithmetic, which is a nuisance. Elvish does, though.
I set myself a little task: write a program which reads from standard in, prints the number of lines read, then prints the input. It’s an interesting task because it must cache the input.
Here’s what I cam up with in elvish:
#!/usr/bin/env elvish contents = [(cat )] echo (count $contents) for line $contents { echo $line }
Here’s the equivalent I write in awk:
{ i += 1; line[i] = $0; } END{ print i; for(idx=0; idx<i; idx++) print line[idx]; }
As you can see, elvish manages the same thing in less than half the number of lines.
Here’s my C++ version:
#include <iostream> #include <string> #include <vector> int main() { std::vector<std::string> lines; std::string line; int nlines = 0; while(std::getline(std::cin, line)) { nlines++; lines.push_back(line); } std::cout << nlines << "\n"; for(std::vector<std::string>::iterator it = lines.begin(); it != lines.end(); ++it) std::cout << *it << "\n"; return 0; }
That’s 20 lines of code.
Here are the timings of running the scripts:
time awk -f count.awk <derive-2.txt >/dev/null real 0m0.067s user 0m0.004s sys 0m0.002s Although there are some odd timings: time awk -f count.awk <derive-2.txt >/dev/null real 0m0.006s user 0m0.003s sys 0m0.002s
$time elvish count <derive-2.txt >/dev/null real 0m0.052s user 0m0.025s sys 0m0.011s
time ./a.out < derive-2.txt >/dev/null # c++ version real 0m0.006s user 0m0.004s sys 0m0.001s
Awk seemed a little inconsistent in its performance. I’m not sure what’s going on there. It looks like Awk can be a real speed demon, and I’ve even seen it run a little faster than the C++ code. Those Awk guys certainly seem to know how to optimise stuff.
Elvish is certainly worth checking out. I’m not sure about its runtime speed, though.
#!/usr/bin/env rc
ifs = () nl = `{echo}
ifs = $nl contents = `{$PLAN9/bin/read -m}
echo $#contents
for(eachline in $contents) echo $eachline
Using rc shell:
http://doc.cat-v.org/plan_9/4th_edition/papers/rc
https://www.in-ulm.de/~mascheck/bourne/unix-faq.shell.rc
https://tools.suckless.org/9base/
https://github.com/rakitzis/rc
Pretty cool.
Also, using shell: ls | pee “wc -l” cat
See pee explained at https://www.ostechnix.com/moreutils-collection-useful-unix-utilities/