Μπορείς να ορίσεις τις δικές σου προσαρμοσμένες συναρτήσεις στο jq για να ενσωματώσεις όποια λογική χρειάζεσαι.
Οι συναρτήσεις λειτουργούν ακριβώς όπως οι ενσωματωμένες: παίρνουν μια είσοδο και παράγουν μηδέν, μία ή περισσότερες εξόδους.
Μπορείς να ορίσεις μια συνάρτηση jq χρησιμοποιώντας την εξής σύνταξη:
# no arguments
def funcname: expression;
# or with arguments
def funcname(args): expression;
def,jq, μπορείς να χρησιμοποιήσεις όποια κενά θέλεις για ευαναγνωσιμότητα.Οι συναρτήσεις πρέπει να ορίζονται πριν χρησιμοποιηθούν: αυτό είναι σφάλμα:
def A: B(10);
def B(n): n + 1;
A
# => error: B/1 is not defined
Αυτό σημαίνει ότι πρέπει να τοποθετείς τις συναρτήσεις στην αρχή του κώδικα jq, πριν από την "κύρια" έκφραση.
Οι συναρτήσεις μπορούν να είναι εμφωλευμένες:
def A:
def B(n): n + 1;
B(10)
;
A
# => 11
Εδώ, η συνάρτηση B είναι ορατή μόνο στο σώμα της A.
Μια συνάρτηση εισάγει μια νέα εμβέλεια για μεταβλητές και εμφωλευμένες συναρτήσεις.
Τα ορίσματα συνάρτησης χωρίζονται με ερωτηματικά και όχι με κόμματα. Για παράδειγμα, μια συνάρτηση που παίρνει έναν αριθμό, και μετά προσθέτει έναν αριθμό και πολλαπλασιάζει με έναν αριθμό:
def add_mul(adder; multiplier): (. + adder) * multiplier;
10 | add_mul(5; 4) # => 60
Τα ερωτηματικά είναι απαραίτητα επειδή το κόμμα έχει ήδη σκοπό στο jq: έναν τελεστή που ενώνει ροές.
Χρησιμοποιώντας κόμμα αντί για ερωτηματικό, θα επιχειρηθεί να γίνουν δύο κλήσεις σε μια συνάρτηση add_mul με ένα όρισμα, η οποία δεν υπάρχει και επομένως θα αποτύχει στην πρώτη απόπειρα κλήσης:
10 | add_mul(5, 4)
# error: add_mul/1 is not defined
Τα ορίσματα συνάρτησης είναι φίλτρα, όχι τιμές. Με αυτή την έννοια, λειτουργούν όπως αυτό που άλλες γλώσσες περιγράφουν ως callbacks:
Χρησιμοποιώντας τη συνάρτηση add_mul ως παράδειγμα:
10 | add_mul(. + 5; . - 2) # => 200
Τι συμβαίνει εδώ;
adder παίρνει την έκφραση . + 5
. + adder, αυτό γίνεται . + . + 5
. == 10
multiplier είναι η έκφραση . - 2
25 * 8 == 200
Μερικές φορές θα θέλεις να "υλοποιήσεις" ένα όρισμα σε μια μεταβλητή:
def my_func(arg):
arg as $arg
| other stuff ...
;
Υπάρχει μια συντομογραφία για αυτό:
def my_func($arg):
other stuff ...
;
Σημείωσε ότι αυτό είναι απλώς "συντακτική ζάχαρη": το όνομα arg χωρίς $ είναι ακόμα στην εμβέλεια της συνάρτησης.
Οι συναρτήσεις έχουν ένα πλήθος ορισμάτων: τον αριθμό των ορισμάτων που δέχονται.
Οι συναρτήσεις μπορούν να χρησιμοποιήσουν το ίδιο όνομα με διαφορετικά πλήθη ορισμάτων.
Η ενσωματωμένη συνάρτηση range το δείχνει αυτό: τα range/1, range/2 και range/3 συνυπάρχουν.
Αυτό μπορεί να είναι χρήσιμο για τον ορισμό αναδρομικών συναρτήσεων που μεταφέρουν κατάσταση μέσω ορισμάτων.
Για παράδειγμα, η map θα μπορούσε να υλοποιηθεί ως εξής:
def my_map($accumulator; func):
if length == 0
then $accumulator
else first as $elem | .[1:] | my_map($accumulator + [$elem | func]; func)
end
;
def my_map(func):
my_map([]; func)
;
[1, 2, 3, 4] | my_map(. * 10) # => [10, 20, 30, 40]
Το jq θα εκτελέσει βελτιστοποίηση ουράς, αλλά μόνο για συναρτήσεις με 0 ορίσματα.
Μια ενότητα jq είναι ένα αρχείο που περιέχει μόνο συναρτήσεις.
Οι ενότητες συμπεριλαμβάνονται σε ένα πρόγραμμα jq με τις εντολές include ή import.
Σε αυτή την άσκηση θα παίξεις με ένα τηλεκατευθυνόμενο αυτοκίνητο, που επιτέλους μάζεψες αρκετά χρήματα για να αγοράσεις.
Τα αυτοκίνητα ξεκινούν με γεμάτες (100%) μπαταρίες. Κάθε φορά που οδηγείς το αυτοκίνητο χρησιμοποιώντας το τηλεχειριστήριο, διανύει 20 μέτρα και καταναλώνει ένα τοις εκατό της μπαταρίας. Το παρατσούκλι του αυτοκινήτου δεν είναι γνωστό μέχρι να δημιουργηθεί.
Το τηλεκατευθυνόμενο αυτοκίνητο έχει μια φανταχτερή οθόνη LED που δείχνει δύο πληροφορίες:
"<METERS> meters"."Battery at <PERCENTAGE>%".Αν η μπαταρία είναι στο 0%, δεν μπορείς πια να οδηγήσεις το αυτοκίνητο και η ένδειξη μπαταρίας θα δείχνει "Battery empty".
Υλοποίησε τη συνάρτηση new_remote_control_car/0 ώστε να επιστρέφει ένα ολοκαίνουργιο αντικείμενο τηλεκατευθυνόμενου αυτοκινήτου:
new_remote_control_car
# => {
# "battery_percentage": 100,
# "distance_driven_in_meters": 0,
# "nickname": null
# }
Υλοποίησε τη συνάρτηση new_remote_control_car/1 ώστε να επιστρέφει ένα ολοκαίνουργιο αντικείμενο τηλεκατευθυνόμενου αυτοκινήτου με ένα δεδομένο παρατσούκλι:
new_remote_control_car("Blue")
# => {
# "battery_percentage": 100,
# "distance_driven_in_meters": 0,
# "nickname": "Blue"
# }
Υλοποίησε τη συνάρτηση display_distance/0 που παίρνει ως είσοδο ένα αντικείμενο αυτοκινήτου και επιστρέφει τη συμβολοσειρά απόστασης όπως εμφανίζεται στην οθόνη LED:
new_remote_control_car | display_distance
# => "0 meters"
Υλοποίησε τη συνάρτηση display_battery/0 που παίρνει ως είσοδο ένα αντικείμενο αυτοκινήτου και επιστρέφει τη συμβολοσειρά ποσοστού μπαταρίας όπως εμφανίζεται στην οθόνη LED:
new_remote_control_car | display_battery
# => "Battery at 100%"
Αν η μπαταρία είναι στο 0%, η ένδειξη μπαταρίας θα δείχνει "Battery empty".
Υλοποίησε τη συνάρτηση drive/0 που:
new_remote_control_car("Red") | drive
# => {
# "battery_percentage": 99,
# "distance_driven_in_meters": 20,
# "nickname": "Red"
# }
Ενημέρωσε τη συνάρτηση drive/0 ώστε να μην αυξάνει την απόσταση που διανύθηκε ούτε να μειώνει το ποσοστό μπαταρίας όταν η μπαταρία είναι άδεια (στο 0%):
{
battery_percentage: 0,
distance_driven_in_meters: 2000,
nickname: "Red"
} | drive
# => {
# "battery_percentage": 0,
# "distance_driven_in_meters": 2000,
# "nickname": "Red"
# }
Γράψου στο Exercism για να μάθεις και να κατακτήσεις jq με 12 έννοιες75 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.