Η έννοια Basics παρουσίασε δύο τρόπους για να ορίσεις μια συνάρτηση.
Γενικότερα, η πολυγραμμική μορφή:
function muladd(x, y, z)
x * y + z
end
Η μορφή "ανάθεσης", ή μορφή "μίας γραμμής", για σύντομους ορισμούς:
muladd(x, y, z) = x * y + z
Σε μια τρίτη, ακόμη πιο σύντομη μορφή, μια σύντομη συνάρτηση μιας χρήσης μπορεί να δημιουργηθεί χωρίς όνομα:
julia> map(x -> 2x, 1:3)
4-element Vector{Int64}:
2
4
6
julia> map((x, y) -> x * y, 1:3, 4:6)
3-element Vector{Int64}:
4
10
18
Σε αυτή την περίπτωση, το x -> 2x είναι μια "ανώνυμη συνάρτηση".
Αυτό είναι ισοδύναμο με αυτό που κάποιες άλλες γλώσσες ονομάζουν "συνάρτηση λάμδα".
Σημείωσε ότι τα πολλαπλά ορίσματα χρειάζονται παρενθέσεις, όπως στο (x, y) -> x * y.
Οι ανώνυμες συναρτήσεις είναι συνηθισμένες στον κώδικα Julia, ειδικά όταν συνδυάζονται με συναρτήσεις υψηλότερης τάξης όπως οι map() και filter().
Μέχρι τώρα στο πρόγραμμα σπουδών, έχουμε δει μόνο συναρτήσεις που έχουν έναν συγκεκριμένο αριθμό ορισμάτων και απαιτούν από τις κλήσεις συνάρτησης να τα παρέχουν όλα, με τη σωστή σειρά. Αυτό θα ήταν περιοριστικό και άβολο, οπότε υπάρχουν αρκετές άλλες επιλογές.
Όπως πολλές γλώσσες, η Julia επιτρέπει στους ορισμούς συναρτήσεων να παρέχουν προεπιλεγμένες τιμές για μεμονωμένα ορίσματα.
Η κλήση συνάρτησης μπορεί τότε είτε να παρέχει μια τιμή για αυτό το όρισμα, είτε να το παραλείπει και να βασίζεται στην προεπιλογή.
julia> f(x, y=10) = x * y
f (generic function with 2 methods)
julia> f(2, 3)
6
julia> f(2)
20
Όλα τα ορίσματα χωρίς προεπιλογές πρέπει να έρχονται πριν από οποιοδήποτε όρισμα με προεπιλογή, που σημαίνει ότι το f(x=2, y) θα ήταν άκυρο.
Όλα τα παραδείγματα μέχρι τώρα χρησιμοποιούν positional arguments, όπου οι τιμές που παρέχονται σε μια κλήση συνάρτησης πρέπει να ταιριάζουν με τη σειρά των αντίστοιχων ορισμάτων στον ορισμό της συνάρτησης.
Όπως πολλές γλώσσες, η Julia επιτρέπει επίσης keyword arguments.
Οι κλήσεις συνάρτησης πρέπει να καθορίζουν το όνομα του ορίσματος, αλλά πολλά ορίσματα λέξεων-κλειδιών μπορούν στη συνέχεια να καθοριστούν με οποιαδήποτε σειρά.
Ένα χαρακτηριστικό γνώρισμα της Julia είναι ότι τα ορίσματα λέξεων-κλειδιών (αν υπάρχουν) στον ορισμό της συνάρτησης πρέπει να προηγούνται από μια άνω τελεία ;, για να ξεχωρίζουν από τυχόν θεσιακά ορίσματα.
Μια κλήση συνάρτησης μπορεί να χρησιμοποιήσει είτε ; είτε , μεταξύ του τελευταίου θεσιακού ορίσματος και του πρώτου ορίσματος λέξης-κλειδιού.
julia> b(x; y) = x + y
b (generic function with 1 method)
julia> b(2, y=3)
5
# keyword is required when calling
julia> b(2, 3)
ERROR: MethodError: no method matching b(::Int64, ::Int64)
The function `b` exists, but no method is defined for this combination of argument types.
Οι προεπιλεγμένες τιμές μπορούν προαιρετικά να καθοριστούν, ακριβώς όπως στα θεσιακά ορίσματα.
Είναι συνηθισμένο να καταλήγεις με σύνταξη όπως myarg=myarg μέσα σε μια κλήση συνάρτησης, όταν μια μεταβλητή με το ίδιο όνομα με την παράμετρο έχει υπολογιστεί εκ των προτέρων.
Σε αυτή την περίπτωση επιτρέπεται μια συντομευμένη σύνταξη:
julia> width = 4.0
4.0
julia> height = √ width
2.0
julia> area(; width, height) = width * height
area (generic function with 1 method)
# repetition
julia> area(; width=width, height=height)
8.0
# shorthand form
julia> area(; width, height)
8.0
Αυτά είναι τα καθιερωμένα ονόματα για μια χρήσιμη πτυχή της σύνταξης της Julia, σε περίπτωση που αναρωτιόσουν.
Και τα δύο αναφέρονται στον τελεστή ....
Το splatting χρησιμοποιείται σε κλήσεις συναρτήσεων, για να επεκτείνει συλλογές σε μεμονωμένες τιμές που απαιτεί η συνάρτηση.
Ίσως είναι πιο εύκολο να το δείξεις παρά να το εξηγήσεις:
julia> fxyz(x, y, z) = x * y * z
fxyz (generic function with 1 method)
julia> xyz = [2, 3, 4]
3-element Vector{Int64}:
2
3
4
# Using the vector directly in a function call is invalid
julia> fxyz(xyz)
ERROR: MethodError: no method matching fxyz(::Vector{Int64})
The function `fxyz` exists, but no method is defined for this combination of argument types.
# splatting converts the vector to 3 numbers, used as positional arguments
julia> fxyz(xyz...)
24
Κάποιες "κλήσεις συναρτήσεων" κρύβονται από συντακτική ζάχαρη, οπότε το splatting μπορεί να χρησιμοποιηθεί και με λιγότερο προφανείς τρόπους.
Για παράδειγμα, η πολλαπλή ανάθεση χρησιμοποιεί εσωτερικά μια συνάρτηση κατασκευής πλειάδας:
julia> first, rest... = [1, 2, 3, 4]
4-element Vector{Int64}:
1
2
3
4
julia> first
1
julia> rest
3-element Vector{Int64}:
2
3
4
Τα ορίσματα λέξεων-κλειδιών μπορούν επίσης να παρασχεθούν με splatting, συνήθως χρησιμοποιώντας ένα named tuple.
Ένα Dict θα λειτουργήσει επίσης, αλλά τα κλειδιά πρέπει να είναι σύμβολα (οι συμβολοσειρές δεν θα λειτουργήσουν εδώ).
# function with 3 keyword arguments
julia> fabc(; a, b, c) = a + b + c
fabc (generic function with 1 method)
# named tuple
julia> abc_nt = (a=2, b=3, c=4)
(a = 2, b = 3, c = 4)
# there are no positional arguments, so need to use ; before kw argument
julia> fabc(;abc_nt...)
9
# Dict
julia> abc_dict = Dict(:a=>2, :b=>3, :c=>4)
Dict{Symbol, Int64} with 3 entries:
:a => 2
:b => 3
:c => 4
julia> fabc(;abc_dict...)
9
Το slurping χρησιμοποιείται στον ορισμό της συνάρτησης, για να συσκευάσει έναν αυθαίρετο αριθμό μεμονωμένων τιμών σε μια συλλογή.
julia> f_more(i, j, more...) = i + j + sum(more)
f_more (generic function with 1 method)
julia> f_more(1, 3, 5, 7, 9, 11)
36
Το όνομα του ορίσματος που συλλέγεται με slurping (σε αυτή την περίπτωση το more) δεν παίζει ρόλο.
Ο τύπος αυτής της μεταβλητής επιλέγεται από τον μεταγλωττιστή, αλλά για τα θεσιακά ορίσματα είναι πιθανότατα tuple ή κάτι παρόμοιο.
Τα ορίσματα λέξεων-κλειδιών μπορούν επίσης να συλλεχθούν με slurping, δίνοντας ένα Dict (ή κάτι παρόμοιο).
julia> f_kwslurp(x, y; switches...) = :mult in keys(switches) ? x * y : x + y
f_kwslurp (generic function with 1 method)
julia> f_kwslurp(5, 6; mult=true)
30
julia> f_kwslurp(5, 6)
11
Οποιαδήποτε ορίσματα λέξεων-κλειδιών μπορούν να χρησιμοποιηθούν στην κλήση. Ο ορισμός της συνάρτησης αποφασίζει σε ποιες λέξεις-κλειδιά θα ανταποκρίνεται και ποιες θα αγνοεί.