Juttua funktioiden nimi-parametreista ja siitä ettei ole tarvetta palauttaa niitä - mutta esitettynä toisin kuin aikaisemmin:
- esitieto: myös BASH ylläpitää reaaliaikaista muuttuja-taulua muuttujiensa arvoista ja antaa funktioidensakin lukea muuttuja-tauluaan.
BASH:illa on vain yksi muisti - siis funktioiden ja pää-ohjelman muisti on sama. Asian voi varmistaa käskyillä:
function koe () { echo $a ;}; a=muisti_on_yhteistä; koe
function koe () { a=muisti_on_yhteistä ;}; koe; echo $a
function koe () { a="muutettu funktiossa" ;}; a="määritelty pää-ohjelmassa"; echo "$a"; koe; echo "$a"
Niiden kummankin tulee onnistua sillä BASH:ssa on jonkunverran sellaista joka toimii toiseen suuntaan mutta toiseen ei. Virtuooseille tuo tieto muistien yhteneväisyydestä on ilmamuuta opetettu joten miksi virtuoosit ovat kuitenkin aina puhuneet siitä ettei BASH osaa parametreja palauttaa sillä eihän koko palauttamisessa näin-ollen ole järjen hilkkuakaan? Mutta ei tässä kohdassa vielä 'palauttamisesta' ole kyse vaan se käsitellään seuraavassa kohdassa
Mutta toisaalta ainoastaan nimi-parametreja käytettäessä ne voidaan 'palauttaa' eikä niiden toimimaan saaminen ole ihan yksinkertaista sillä yhden asian takia on saatettu tehtdä väärä johtopäätös siitä kuinka parametrit toimivat: kun funktioon siirretään muuttuja nimi-parametrina siirretäänkin vain sen nimi eikä sillä ole siirron jälkeen vielä niitä arvoja kuin 'pääohjelman' saman-nimisen muuttujalla - sama muuttuja siitä tulee vasta kun se saa samat arvotkin jollain tavalla. Sentakia esimerkiksi käsky:
function koe () { $1=$((2*$1)) ;}; a=2; koe a; echo $a
ei onnistu. Mutta tulostuksesta näkee että funktion alussa oleva $1 kaipaa sitä käyttävää käskyä ja 'man let' kertoo välittömästi että let toden-näköisesti kelpaa - tai olisi kertonut elleivät virtuoosit olisi man-sivua poistaneet - jotta voisivat elleen väittää BASH:ia kyvyttömäksi. Sivu 'man eval' on myös poistettu ja kielletty käskyn eval käyttäminen. Käsky read on taas niin vaikea löytää etteivät virtuoosit sitä ole läytäneet. Siis seuraava toimii:
function koe () { let $1=$((2*$1)) ;}; a=2; koe a; echo $a
Automatiikka arvon hakemiseksi sieltä muuttuja-taulusta siis puuttuu ja kun sen lisää niin alkaa toimia.
- automatiikka puuttuu useista muistakin tehtävistä - sillä BASH:in tarkoituksena on opettaa sekin mitä mikin toiminto onnistuakseen vaatii ja se myös tarjoaa palikat sen tekemiseksi. Vikana on kylläkin se että virtuoosit 'unohtivat' aikoinaan mikä BASH:in olisi tarkoitus tehdä eivätkä ole esittäneet yhtään esimerkkiä minkään toiminnon automatiikasta - tai luultavasti ovat tehneet ja senjälkeen 'unohtaneet'.
On parasta kuvata esimerkeillä kuinka niitä nimi-parametreja ei palauteta:
function tuplaa_luku () { let "$1 <<=1" ;}; a=55; tuplaa_luku a; echo $a # Toimii vain kokonaisluvuille. Sama toisella tavalla:
function tuplaa_luku () { read<<<$((2*$1)) $1 ;}; a=55; tuplaa_luku a; echo $a # eka $1 viittaa funktioon tulleeseen arvoon ja toka $1 viittaa tulevaan arvoon.
function tuplaa_luku () { read<<<$(eval echo 2*\$$1 | bc) $1 ;}; a=55.55; tuplaa_luku a; echo $a # toimii sekä kokonais- että desimaaliluvuilla. (käsky eval kehottaa tulkkaamaan seuravan kahdesti - ensimmäisellä kierroksella $1
ratkaistaan ja \ suojelee ensimmäistä $:ä - mutta toisella kierroksella suoja poistuu ja $a tulkataan).
matriisitkin toimivat näin:
function koe () { let $1[$2]=$((2*$1[$2]));}; a=(1 2 3); koe a 1; printf "%s\n" ${a[@]}
- niin tässä kuin kaikessa muussakin BASH:in yksi ominaisuus saa tekemään vääriä johtopäätöksiä: kaikki minkä teet tallettuu päätteeseen. Kun siis jotain käskyä kokeilee niin viimeisellä koe-kerralla ensin suljetaan pääte, avataan uusi pääte
ja haetaan koe-käsky takaisin näytölle nuoli-ylös näppäimellä.
- jos eval:ia ei halua käyttää niin seuraava toimii myös nopeasti koostaan huolimatta - siinä kirjaimellisesti käydään lukemassa sitä muuttuja-taulua joten se toimii kaikenlaisille muuttujile, myös matriiseille ja tekstijonoille - jopa muuttujien attribuutit siirtyvät - integer, vakio ja semmoset - attribuutti-määritykset löytää esimerkiksi sivulta:
https://linuxcommand.org/lc3_man_pages/declareh.html.
Sen avulla saa nimi-parametrit toimimaan lukemalla funktiossa oltaessa lukemalla muuttuja-taulu selväsanaisesti - ja moni-mutkaisemmissa asioissa se onkin tarpeen. Esimerkiksi:
function tuplaa_luku () { apu1=$(declare -p $1); declare ${apu1:8:2} apu2=${apu1#*=}; apu2=${apu2%\"}; apu2=${apu2#\"}; read<<<$(kerro18 2 $apu2) $1 ;}; a=55555555.55555555; tuplaa_luku a; echo $a
- skripti on nopea kirjoittaa mille lasku-kaavalle tahansa sillä muun osan voi kopioida-liimata ja ainoastaan: $(kerro18 2 $apu2) paikalle tulee laskukaava
- tai toinen tapa - kyseessä on tekstijonon siirtäminen nimi-parametrina ja tehtävänä erottaa tekstijonon viimeinen sana:
function koe () { apu=$(declare -p $1); apu=${apu##*=}; apu=$( echo $apu | tr -d \"); read<<<${apu##* } $1 ;}; a="kissa kuumalla katolla"; koe a; echo $a
- matriisin siirtäminen nimi-parametrina ja palautus matriisin jokainen jäsenen korotettuna potenssiin kolme - vähän toisella tavalla:
function foreach () { name=$1; name=($(declare -p | grep 'a '$name | grep -Po \".*?\" | tr -d \" | tr '\n' " " )); for n in ${name[@]}; do eval $1[$n-1]=$(($1[$n-1]**3)); done ;}; apu=({1..1000}); time foreach apu; printf "%s\n" "${apu[@]}"
- tai matriisin lukeminen muuttujataulusta kun nimi on tullut nimi-parametrina:
function koe () { apu1=$(declare -p $1); declare ${apu1:8:2} apu2=${apu1#*=}; apu2=${apu2%\"}; apu2=${apu2#\"}; apu2[2]=oh-hoh; unset $1; read<<<${apu2[@]} $1;}; matrix=(1 2 3 4 5 6 7 8 9); koe matrix; echo ${matrix[@]}
# unset $1 nollaa $1:n vanhan arvon sillä muuten vanhasta arvosta osa kummittelisi - poista se ja katso mitä tapahtuu.
Funktio kerro18 toimii hieman eritavalla: esimerkiksi siinä kelvottomasti toimivassa käskyssä:
function koe () { $1=$((2*$1)) ;}; a=2; koe a; echo $a
on pajon oikeaakin toimintaa. Siitä saa sen oikein toimivan erilleen - ja siitä pääsee oikeaan tulokseen hiljaa hivuttamalla.
---
BASH-virtuoosien netti-kirjoituksista selviää että jotkut virtuoosit tunsivat nämä toiminta-tavat jo kauan sitten. Mutta he eivät puhuneet asioista oikein mitään koska BASH:ista haluttiin eroon ja kyvykkäästä BASH:ista olisi ollut mahdoton päästä eroon. Mutta eivät malttaneet olla täysin hiljaakaan joten lukemattomista eri ihmisten omakehuista sai koottua kokonaiskuvan - sillä jokainen kehuu omalla ja ihan erilaisella tavalla kuin muut.
Jotkut erittäin harvat opettavat BASH:ia edelleen ja uusia oppaitakin julkaistaan silloin-tällöin. Mutta mitään uutta ei edes harkita omaksuttavan - vaikka aina toimivaa skriptiä ei pitäisi voida jättää huomiotta. Eihän vuosikymmenien aikaisten virtuoosin puheiden tylytystä voi silti noinvain hyväksyä - mutta toisaalta potaskaa puhuva opettaja on tosi nolo juttu.