Fish is a great command-line shell targeted on programmers. It has some cool programming-like features hereat.

Image for post
Image for post

The Constructor

The Person function should create the instance reference and pass the parameters to it.

function Person -d'Person class'
set -l id (uuidgen)
set -l self __Person_(echo $id | sed 's!-!!g')
argparse n/name= s/surname= b/birth= -- $argv

Accessor Methods

We can create three getters (read accessor methods) called id, fullname, and birth. For that we use alias:

  alias $self.id="echo -n $id"
alias $self.fullname="echo -n $_flag_name $_flag_surname"
alias $self.birth="echo -n $_flag_birth"

Instance Methods

For sample purpose, we can create a method for serialisation. As Fish doesn’t support closures, all private info must use the Fish approach for weakly private data, and the method must be built by eval tool:

  eval "function $self.string
printf '%s (%s): %s' ($self.fullname) ($self.id) ($self.birth)
end"

Mutable Attributes

Again Fish doesn’t support closures, thereat it’s necessary to use global variables. For example, a person can have metadata:

  set -g "$self"_metadata
  eval "function $self.metadata -a metadata
test -n \"\$metadata\"
and set $self""_metadata \"\$metadata\"
echo -n \$$self""_metadata
end"

Returning the Instance

At the constructor block’s end, it’s necessary to return the instance global id. The return statement returns the status code, so it’s not what we want.

  echo -n $self
end

The Destructor

The Fish garbage collector cannot clean up global variables, not even weakly private when their references die. So we need to do it explicitly. Therefore we created a destructor block.

function delete -d'garbage collector for class instances'
for instance in $argv
for funcname in (functions --all)
string match "$instance.*" -- "$funcname" >/dev/null
and functions --erase "$funcname"
end
    set | awk '{ print $1; }' | while read envvar
string match "$instance\_*" -- "$envvar" >/dev/null
and set --erase "$envvar"
end
end
end

Using the Class

Now an example of using the class:

begin
set -l person_a (Person -nJohn -sDoe -b1970-01-01)
set -l person_b (Person -nPedro -sde\ Lara -b1925-02-25)
$person_a.metadata nobody >/dev/null
$person_b.metadata showman >/dev/null
printf '%64s, %s\n' ($person_a.string) ($person_a.metadata)
printf '%64s, %s\n' ($person_b.string) ($person_b.metadata)
delete $person_a $person_b
end
     John Doe (DE93A63C-8F1D-454F-BD01-C9EF0E1683AF): 1970-01-01, nobody
Pedro de Lara (B3169DFE-DD8F-49B1-9601-4E05F2CE40F9): 1925-02-25, showman

Written by

Musician, senior software engineer, autistic, and autistic parent (not necessarily in this order)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store