Perché linguaggi come scripting di shell e perl usano $ davanti ai nomi di variabili?

2

Contesto

Forse mi limito ad usare linguaggi in stile C-esque ma avere un sigillo davanti a una variabile (ad esempio $VAR ) mi sembra sempre strano.

Domanda

Perché alcuni linguaggi come Perl e lo script di shell hanno sigilli davanti ai nomi delle variabili?

Riesco a vedere che abbia senso per linguaggi più vecchi come Basic (anni '60) in cui l'interprete potrebbe non essere abbastanza intelligente da sapere a quale tipo di variabile ci riferiamo. Guardando a C negli anni '70, vediamo che tutto è finito. Negli anni '80 apparvero shell e Perl e usarono la sigla notazione ancora Tcl, Erlang e altri come C ++ no. Negli anni '90, vediamo Python e Ruby che non hanno affatto sigilli. Forse esistono, ma non ho visto un linguaggio di programmazione sviluppato di recente utilizzare sigilli. Tuttavia, ho visto il linguaggio fare altre cose come decoratori di python @staticmethod che possono assomigliare a sigilli, ma sono usati in un contesto diverso.

Non codifico molto in Perl ma per bash, printf è una funzione e racchiusa in una sostituzione di comando, $(printf ...) crea sprintf da C. Con entrambe queste opzioni, non vedo guadagni di diciamo usando "This ${magic}String" su printf "This %sString" "$magic" specialmente quando le stringhe diventano veramente lunghe. Allo stesso modo, ${#STR} è fonte di confusione, specialmente per i programmatori più recenti che non sanno cosa faccia quel pezzo di codice, mentre len str è più facile da leggere. Forse sto solo prendendo a pugni qualcosa che non ha importanza e tutti accettano e passano.

    
posta unsignedzero 24.03.2016 - 07:54
fonte

2 risposte

2

In the 1990s, we see Python and Ruby not having sigils at all.

Ruby non ha sigilli? Ruby è il re dei sigilli!

  • $ è una variabile globale o pseudo-globale,
  • @ è una variabile di istanza,
  • @@ è una variabile di gerarchia di classi e
  • (non tecnicamente un sigillo, ma simile nello spirito) una lettera maiuscola è una variabile costante.

E nei due casi in cui non è un sigillo, c'è un'ambiguità tra variabili e metodi:

foo

è una chiamata al metodo o una variabile? Ruby dice: entrambi! Se ha analizzato ( non eseguito) un compito prima, assume, è una variabile locale, altrimenti assume, è una chiamata di metodo. Quindi:

foo # method call

if false
  foo = 42 # it doesn't matter that this isn't executed, only parsed
end

foo # local variable
# => nil
# un-initialized local variables evaluate to nil

Ok, e cosa succede se voglio chiamare un metodo chiamato foo adesso? Bene, ho bisogno di chiarire a Ruby che intendo chiamare un metodo:

foo() # pass an argument list, only methods can take arguments

self.foo # provide an explicit receiver, however doesn't work for private methods

Questo pone un altro problema: se ho una funzione assegnata a una variabile, come posso chiamare quella funzione? Non posso farlo con foo() , perché questo chiama un metodo chiamato foo , devo dire foo.() .

Per le costanti, la situazione è simile. Foo è sempre interpretato come costante, per trattarlo come una chiamata al metodo, devi dire Foo() o self.Foo .

In Python, questa ambiguità viene risolta richiedendo sempre un ricevitore esplicito per tutto ciò che non è una variabile e richiede sempre parentesi per le chiamate. Quindi, una variabile locale è sempre foo , una chiamata al metodo è sempre self.foo() e il richiamo di una funzione memorizzata in una variabile locale è sempre foo() . Una variabile di istanza è sempre self.foo .

ECMAScript lo risolve disponendo di un singolo spazio dei nomi per funzioni e variabili, in modo che sia impossibile avere sia una funzione che una variabile denominate foo :

let foo = 42;

function foo() {};
// TypeError: Identifier 'foo' has already been declared
    
risposta data 24.03.2016 - 12:45
fonte
5

Nella shell, dove si hanno script di shell, con un ambiente che può essere manipolato dal chiamante dello script, è davvero molto utile se si riesce a distinguere tra "questo è un riferimento variabile" e "questo è testo" senza avere per consultare l'ambiente.

Se una qualsiasi "variabile definita" sarebbe sostituita dal suo valore, il seguente non sarebbe sicuro in uno script di shell:

ls /tmp/*

Perché se volessi che diventasse dannoso, tutto ciò che avresti bisogno sarebbe fare quanto segue:

ls=rm
export ls

Quindi avere una sorta di segnale distinto che dice "sì, questo è il recupero del valore di una variabile" è molto utile.

Perl (probabilmente) ha ottenuto questo dalla shell, ma lo ha esteso per utilizzare vari simboli di prefisso per denotare i tipi di dati, quindi $foo è una variabile scalare, ma @foo è una variabile di matrice.

    
risposta data 24.03.2016 - 11:30
fonte

Leggi altre domande sui tag