Úkol (informatika) - Assignment (computer science)

V počítačovém programování příkaz přiřazení nastaví a/nebo znovu nastaví hodnotu uloženou v úložných místech označených názvem proměnné ; jinými slovy, zkopíruje hodnotu do proměnné. Ve většině imperativních programovacích jazycích je přiřazovací příkaz (nebo výraz) základní konstrukcí.

Dnes je pro tuto operaci nejčastěji používán zápis (původně Superplan 1949–51, propagovaný Fortranem 1957 a C ). Druhým nejčastěji používaným zápisem je (původně ALGOL 1958, popularizoval Pascal ) ,. Používá se také mnoho dalších notací. V některých jazycích je použitý symbol považován za operátor (což znamená, že příkaz přiřazení jako celek vrací hodnotu). Jiné jazyky definují přiřazení jako příkaz (což znamená, že jej nelze použít ve výrazu). x = exprx := expr

Přiřazení obvykle umožňují proměnné uchovávat různé hodnoty v různých časech během její životnosti a rozsahu . Některé jazyky (především přísně funkční jazyky) však tento druh „destruktivního“ přeřazení neumožňují, protože by to mohlo znamenat změny nelokálního stavu. Účelem je prosadit referenční transparentnost , tj. Funkce, které nezávisí na stavu některé proměnné (proměnných), ale produkují stejné výsledky pro danou sadu parametrických vstupů v jakémkoli časovém okamžiku. Moderní programy v jiných jazycích také často používají podobné strategie, i když méně přísné, a pouze v určitých částech, aby snížily složitost, obvykle ve spojení s doplňujícími se metodikami, jako je strukturování dat , strukturované programování a objektová orientace .

Sémantika

Operace přiřazení je proces v imperativním programování, ve kterém jsou různé hodnoty spojeny s konkrétním názvem proměnné v průběhu času. Program v takovém modelu funguje tak, že změní svůj stav pomocí postupných příkazů přiřazení. Primitivy imperativních programovacích jazyků spoléhají na přiřazení k iteraci . Na nejnižší úrovni je přiřazení implementováno pomocí strojních operací , jako je MOVEnebo STORE.

Proměnné jsou kontejnery pro hodnoty. Do proměnné je možné vložit hodnotu a později ji nahradit novou. Operace přiřazení mění aktuální stav provádějícího programu. V důsledku toho je přiřazení závislé na konceptu proměnných . V úkolu:

  • expressionJe hodnocen při současném stavu programu.
  • Je variablepřiřazena vypočtená hodnota, která nahrazuje předchozí hodnotu této proměnné.

Příklad: Za předpokladu, že se ajedná o číselnou proměnnou, přiřazení a := 2*aznamená, že se obsah proměnné apo provedení příkazu zdvojnásobí.

Příklad segmentu kódu C :

int x = 10; 
float y;
x = 23;
y = 32.4f;

V tomto vzorku je proměnná xnejprve deklarována jako int a poté je jí přiřazena hodnota 10. Všimněte si, že deklarace a přiřazení se vyskytují ve stejném příkazu. Ve druhém řádku yje deklarován bez přiřazení. Ve třetím řádku xje přiřazena hodnota 23. Nakonec yje přiřazena hodnota 32,4.

Pro operace přiřazení, je nutné, aby se hodnota expressionje dobře definovaná (to je platný rvalue ), a že variablepředstavuje modifikovatelný subjekt (to je platný modifikovatelná (ne const ) lvalue ). V některých jazycích, obvykle dynamických , není nutné proměnnou deklarovat před přiřazením hodnoty. V takových jazycích je proměnná automaticky deklarována při prvním přiřazení, přičemž rozsah se deklaruje v různých jazycích.

Jediné zadání

Jakékoli přiřazení, které mění stávající hodnotu (např. x := x + 1), Je v čistě funkčních jazycích zakázáno . Ve funkčním programování se nedoporučuje přiřazování ve prospěch jednoho přiřazení, nazývaného také inicializace . Jedno přiřazení je příkladem vazby názvu a liší se od přiřazení, jak je popsáno v tomto článku v tom, že jej lze provést pouze jednou, obvykle při vytvoření proměnné; není povoleno žádné následné přeřazení.

Vyhodnocení výrazu nemá vedlejší účinek, pokud nemění pozorovatelný stav stroje a vytváří stejné hodnoty pro stejný vstup. Imperativní přiřazení může zavést vedlejší efekty a zároveň zničit a učinit starou hodnotu nedostupnou, zatímco ji nahradí novou, a v LISP a funkčním programování se z tohoto důvodu označuje jako destruktivní přiřazení , podobné destruktivní aktualizaci .

Jediné přiřazení je jedinou formou přiřazení, která je k dispozici v čistě funkčních jazycích, jako je Haskell , které nemají proměnné ve smyslu imperativních programovacích jazyků, ale spíše pojmenovávají konstantní hodnoty případně složené povahy s jejich prvky postupně definovanými na vyžádání . Čistě funkční jazyky mohou poskytnout příležitost k paralelnímu provádění výpočtů , čímž se zabrání von Neumannovu zúžení sekvenčního provádění jednoho kroku v čase, protože hodnoty jsou na sobě nezávislé.

Nečisté funkční jazyky poskytují jak jedno přiřazení, tak skutečné přiřazení (ačkoli skutečné přiřazení se obvykle používá s menší frekvencí než v imperativních programovacích jazycích). Například ve Scheme lze u všech proměnných použít jednoduché přiřazení (s let) i skutečné přiřazení (s set!) a pro destruktivní aktualizaci uvnitř seznamů, vektorů, řetězců atd. Jsou k dispozici specializovaná primitiva. V OCaml je povoleno pouze jedno přiřazení pro proměnné prostřednictvím syntaxe; nicméně destruktivní aktualizaci lze použít na prvky polí a řetězců se samostatným operátorem, stejně jako na pole záznamů a objektů, které byly programátorem výslovně prohlášeny za proměnlivé (což znamená, že je lze změnit po jejich počáteční deklaraci). let name = value<-

Mezi funkční programovací jazyky, které používají jedno přiřazení, patří Clojure (pro datové struktury, nikoli vars), Erlang (akceptuje vícenásobné přiřazení, pokud jsou hodnoty stejné, na rozdíl od Haskell), F# , Haskell , JavaScript (pro konstanty), Lava , OCaml , Oz (pro proměnné toku dat, nikoli buňky), raketa (u některých datových struktur, jako jsou seznamy, nikoli symboly), SASL , Scala (pro hodnoty), SISAL , standardní ML . Non- backtracking Prologový kód lze považovat za explicitní jedno přiřazení, explicitní v tom smyslu, že jeho (pojmenované) proměnné mohou být v explicitně nepřiřazeném stavu nebo mohou být nastaveny přesně jednou. Naproti tomu v Haskellu nemohou existovat žádné nepřiřazené proměnné a každou proměnnou lze při vytváření považovat za implicitně nastavenou na její hodnotu (nebo spíše na výpočetní objekt, který bude vytvářet svoji hodnotu na vyžádání ).

Hodnota úkolu

V některých programovacích jazycích příkaz přiřazení vrací hodnotu, zatímco v jiných nikoli.

Ve většině výrazově orientovaných programovacích jazycích (například C ) příkaz přiřazení vrací přiřazenou hodnotu, což umožňuje takové idiomy jako x = y = a, ve kterých příkaz přiřazení y = avrací hodnotu a, ke které je pak přiřazeno x. V příkazu, jako je návratová hodnota funkce, se používá k ovládání smyčky při přiřazování stejné hodnoty proměnné. while ((ch = getchar()) != EOF) {}

V jiných programovacích jazycích, například Scheme , je návratová hodnota přiřazení nedefinovaná a takovéto idiomy jsou neplatné.

V Haskellu neexistuje žádné variabilní přiřazení; ale operace podobné přiřazení (jako je přiřazení k poli pole nebo poli měnitelné datové struktury) obvykle vyhodnocují typ jednotky , který je reprezentován jako (). Tento typ má pouze jednu možnou hodnotu, proto neobsahuje žádné informace. Typicky je to typ výrazu, který je hodnocen čistě kvůli jeho vedlejším účinkům.

Variantní formy zadání

Určité vzorce použití jsou velmi běžné, a proto často mají speciální syntaxi, která je podporuje. Jedná se především o syntaktický cukr ke snížení redundance ve zdrojovém kódu, ale také pomáhá čtenářům kódu porozumět záměru programátora a poskytuje kompilátoru vodítko k možné optimalizaci.

Rozšířené přiřazení

Případ, kdy přiřazená hodnota závisí na předchozím, je tak běžný, že mnoho imperativních jazyků, zejména C a většina jeho potomků, poskytuje speciální operátory zvané rozšířené přiřazení , jako *=, takže a = 2*amísto toho lze psát jako a *= 2. Kromě syntaktického cukru to pomáhá úkolu kompilátoru tím, že objasňuje, že aje možná modifikace proměnné na místě .

Zřetězené přiřazení

Příkaz podobný w = x = y = zse nazývá zřetězené přiřazení, ve kterém je hodnota parametru zpřiřazena více proměnným w, x,a y. Zřetězené přiřazení se často používají k inicializaci více proměnných, jako v

a = b = c = d = f = 0

Ne všechny programovací jazyky podporují řetězové přiřazování. Zřetězené úkoly jsou ekvivalentní posloupnosti přiřazení, ale strategie hodnocení se mezi jazyky liší. U jednoduchých řetězových přiřazení, jako je inicializace více proměnných, na strategii hodnocení nezáleží, ale pokud jsou cíle (hodnoty l) v přiřazení nějakým způsobem propojeny, strategie hodnocení ovlivní výsledek.

V některých programovacích jazycích ( například C ) jsou řetězová přiřazení podporována, protože přiřazení jsou výrazy a mají hodnoty. V tomto případě může být přiřazení řetězec realizován tím, že má úkol pravý-asociativní a úkoly stalo zprava doleva. Například i = arr[i] = f()je ekvivalentní arr[i] = f(); i = arr[i]. V jazyce C ++ jsou k dispozici také pro hodnoty typů tříd deklarováním příslušného návratového typu pro operátor přiřazení.

V Pythonu nejsou příkazy přiřazení výrazy, a proto nemají žádnou hodnotu. Zřetězené přiřazení je místo toho řada příkazů s více cíli pro jeden výraz. Přiřazení se provádějí zleva doprava, takže se i = arr[i] = f()vyhodnotí výraz f(), pak se přiřadí výsledek cíli úplně vlevo ia poté se stejným výsledkem přiřadí dalšímu cíli arr[i]pomocí nové hodnoty i. To je v podstatě ekvivalentní tomu, tmp = f(); i = tmp; arr[i] = tmpže pro dočasnou hodnotu se nevyrábí žádná skutečná proměnná.

Paralelní přiřazení

Některé programovací jazyky, jako je APL , Common Lisp , Go , JavaScript (od 1.7), PHP , Maple , Lua , occam 2 , Perl , Python , REBOL , Ruby a PowerShell umožňují paralelní přiřazení několika proměnných se syntaxí jako :

a, b := 0, 1

který současně přiřadí 0 k aa 1 k b. Toto je nejčastěji známé jako paralelní přiřazení ; to bylo představeno v CPL v roce 1963, pod názvem simultánní přiřazení , a je někdy nazýván vícenásobným přiřazením , ačkoli toto je matoucí při použití s ​​„jediným přiřazením“, protože to nejsou protiklady. Pokud je na pravé straně přiřazení jedna proměnná (např. Pole nebo struktura), tato funkce se nazývá rozbalení nebo zničení přiřazení :

var list := {0, 1}
a, b := list

Seznam bude rozbalen tak, že 0 bude přiřazeno aa 1 až b. Kromě toho,

a, b := b, a

prohodí hodnoty aa b. V jazycích bez paralelního přiřazování by to muselo být napsáno, aby se používala dočasná proměnná

var t := a
a := b
b := t

protože a := b; b := aopouští oba aa bs původní hodnotou b.

Některé jazyky, například Go a Python, kombinují paralelní přiřazování, řazené kolekce členů a automatické rozbalování řazených kolekcí, aby umožnily více návratových hodnot z jedné funkce, jako v tomto příkladu Pythonu,

def f():
    return 1, 2
a, b = f()

zatímco jiné jazyky, jako například C# , zde zobrazené, vyžadují explicitní konstrukci a dekonstrukci řazené kolekce členů pomocí závorek:

(a, b) = (b, a);
(string, int) f() => ("foo", 1);
var (a, b) = f();

To poskytuje alternativu k použití výstupních parametrů pro vrácení více hodnot z funkce. To se datuje do CLU (1974) a CLU pomohlo obecně popularizovat paralelní přiřazování.

C# navíc umožňuje generalizované přiřazení dekonstrukce s implementací definovanou výrazem na pravé straně, protože kompilátor hledá ve výrazu příslušnou instanci nebo metodu rozšíření Deconstruct , která musí mít výstupní parametry pro přiřazené proměnné. Například jedna taková metoda, která by dala třídě, se objeví ve stejném chování jako návratová hodnota f()výše

void Deconstruct(out string a, out int b) { a = "foo"; b = 1; }

V C a C ++ je čárkový operátor podobný paralelnímu přiřazování , protože umožňuje více přiřazení v rámci jednoho příkazu, a = 1, b = 2místo psaní a, b = 1, 2. Toto se používá především pro smyčky a je nahrazeno paralelním přiřazováním v jiných jazycích, jako je Go. Výše uvedený kód C ++ však nezajišťuje dokonalou simultánnost, protože pravá strana následujícího kódu a = b, b = a+1je vyhodnocena po levé straně. V jazycích, jako je Python, a, b = b, a+1přiřadí dvě proměnné souběžně pomocí počáteční hodnoty a pro výpočet nového b.

Přiřazení versus rovnost

Použití znaménka rovnosti =jako operátoru přiřazení bylo často kritizováno kvůli konfliktu s rovnými jako srovnání pro rovnost. To má za následek jak zmatek nováčků v psaní kódu, tak zmatek i zkušených programátorů ve čtení kódu. Použití ekvivalentů pro přiřazení se datuje do jazyka Superplan Heinze Rutishausera , který byl navržen v letech 1949 až 1951 a byl zvláště propagován společností Fortran:

Notoricky známým příkladem špatného nápadu byla volba znaménka rovnosti pro označení úkolu. Vrací se do Fortranu v roce 1957 a byl slepě kopírován armádami jazykových designérů. Proč je to špatný nápad? Protože svrhává stoletou tradici nechat „=“ označovat srovnání pro rovnost, predikát, který je buď pravdivý, nebo nepravdivý. Fortran to ale znamenal jako úkol, prosazování rovnosti. V tomto případě jsou operandy na nerovném základě: Levý operand (proměnná) má být roven pravému operandu (výraz). x = y neznamená totéž jako y = x.

-  Niklaus Wirth , Dobré nápady, přes zrcadlo

Začínající programátoři někdy zaměňují přiřazení s relačním operátorem za rovnost, protože „=“ znamená rovnost v matematice a používá se pro přiřazování v mnoha jazycích. Ale přiřazení mění hodnotu proměnné, zatímco testování rovnosti testuje, zda mají dva výrazy stejnou hodnotu.

V některých jazycích, jako je BASIC , "="se pro operátor přiřazení i relační operátor rovnosti používá znak jedné rovnosti ( ), přičemž kontext určuje, co je míněno. Jiné jazyky používají pro tyto dva operátory různé symboly. Například:

  • V ALGOL a Pascal je operátor přiřazení dvojtečka a znaménko ":="rovnosti ( ), zatímco operátor rovnosti je jeden rovná se ( "=").
  • V C je operátor přiřazení jedno znaménko "="rovnosti ( ), zatímco operátor rovnosti je dvojice znaménka rovnosti ( "==").
  • V R je operátor přiřazení v podstatě <-jako v x <- value, ale v určitých kontextech lze použít jediné znaménko rovnosti.

Podobnost těchto dvou symbolů může vést k chybám, pokud programátor zapomene, která forma („ =“, „ ==“, „ :=“) je vhodná, nebo chybně „ =“, když „ ==“ bylo zamýšleno. Toto je běžný problém s programováním v jazycích, jako je C (včetně jednoho slavného pokusu o backdoor jádra Linuxu), kde operátor přiřazení také vrací přiřazenou hodnotu (stejným způsobem, jakým funkce vrací hodnotu) a lze ji platně vnořit vnitřní výrazy. Pokud by bylo například záměrem porovnat dvě hodnoty v ifpříkazu, přiřazení s velkou pravděpodobností vrátí hodnotu interpretovatelnou jako logická hodnota true, v takovém případě bude thenklauzule spuštěna, což povede k neočekávanému chování programu. Některé jazykové procesory (například gcc ) mohou takové situace detekovat a varovat programátora před potenciální chybou.

Zápis

Dvě nejběžnější reprezentace pro přiřazení kopírování jsou znaménko rovná se ( =) a dvojtečka-rovná se ( :=). Obě formy mohou sémanticky naznačovat buď zadání příkazu nebo přiřazení operátor (který má také hodnotu), v závislosti na jazyku a / nebo použití.

variable = expression Fortran , PL/I , C (a potomci jako C ++ , Java atd.), Bourne shell , Python , Go (přiřazení předem deklarovaných proměnných), R , PowerShell , Nim atd.
variable := expression ALGOL (a deriváty), Simula , CPL , BCPL , Pascal (a potomci jako Modula ), Mary , PL/M , Ada , Smalltalk , Eiffel , Oberon , Dylan , Seed7 , Python (výraz přiřazení), Go (zkratka pro deklarace a definování proměnné), Io , AMPL , ML , AutoHotkey atd.

Mezi další možnosti patří šipka vlevo nebo klíčové slovo, existují však i jiné, vzácnější varianty:

variable << expression Magik
variable <- expression F# , OCaml , R , S
variable <<- expression R.
assign("variable", expression) R.
variableexpression APL , Smalltalk , ZÁKLADNÍ programování
variable =: expression J.
LET variable = expression ZÁKLADNÍ
let variable := expression XQuery
set variable to expression AppleScript
set variable = expression C skořápka
Set-Variable variable (expression) Prostředí PowerShell
variable : expression Macsyma, Maxima , K
variable: expression Rebol
var variable expression skriptovací jazyk mIRC
reference-variable :- reference-expression Simula

Matematické přiřazení pseudo kódu je obvykle znázorněno šipkou doleva.

Některé platformy umísťují výraz vlevo a proměnnou vpravo:

MOVE expression TO variable COBOL
expressionvariable TI-BASIC , Casio BASIC
expression -> variable POP-2 , BETA , R.
put expression into variable LiveCode
PUT expression IN variable ABC

Některé výrazově orientované jazyky, například Lisp a Tcl, jednotně používají syntaxi předpony (nebo postfixu) pro všechny příkazy, včetně přiřazení.

(setf variable expression) Lisp
(set! variable expression) Systém
set variable expression Tcl
expression variable ! Forth

Viz také

Poznámky

Reference