Un punto che non vedo menzionato esplicitamente (anche se amon lo allude) è che la radice quadrata può essere pensata come un'operazione "derivata": se l'implementazione non la fornisce per noi, possiamo scrivere il nostro proprio.
Poiché la domanda è codificata con il design del linguaggio, potremmo prendere in considerazione alcune descrizioni indipendenti dal linguaggio. Sebbene molte lingue abbiano filosofie diverse, è molto comune attraverso i paradigmi utilizzare l'incapsulamento per preservare gli invarianti; vale a dire evitare di avere un valore che non si comporta come suggerirebbe il suo tipo.
Ad esempio, se abbiamo qualche implementazione di interi usando le parole macchina, probabilmente vorremmo incapsulare la rappresentazione in qualche modo (ad esempio per impedire cambiamenti di bit dalla modifica del segno), ma allo stesso tempo abbiamo ancora bisogno di accedere a quei bit per implementare operazioni come addizione.
Alcune lingue potrebbero implementarlo con classi e metodi privati:
class Int {
public Int add(Int x) {
// Do something with the bits
}
private List<Boolean> getBits() {
// ...
}
}
Alcuni con i sistemi dei moduli:
signature INT = sig
type int
val add : int -> int -> int
end
structure Word : INT = struct
datatype int = (* ... *)
fun add x y = (* Do something with the bits *)
fun getBits x = (* ... *)
end
Alcuni con ambito lessicale:
(defun getAdder ()
(let ((getBits (lambda (x) ; ...
(add (lambda (x y) ; Do something with the bits
'add))
E così via. Tuttavia, nessuno di questi meccanismi è necessario per l'implementazione della radice quadrata: può essere implementato usando l'interfaccia pubblica di un tipo numerico, e quindi non ha bisogno di accedere al dettagli di implementazione incapsulati.
Quindi la posizione della radice quadrata dipende dalla filosofia / dal gusto della lingua e dal progettista della biblioteca. Alcuni possono scegliere di mettere "dentro" i valori numerici (ad esempio, renderlo un metodo di istanza), alcuni possono scegliere di metterlo allo stesso livello delle operazioni primitive (questo potrebbe significare un metodo di istanza, o potrebbe significare vivere all'esterno i valori numerici, ma dentro lo stesso modulo / classe / spazio dei nomi, ad esempio come funzione autonoma o metodo statico), alcuni potrebbero scegliere di inserirlo in una raccolta di "helper" funzioni, alcuni potrebbero scegliere di delegarlo a librerie di terze parti.