Myślę, że rozumiem mocne pisanie , ale za każdym razem, gdy szukam przykładów słabego pisania, znajduję przykłady języków programowania, które po prostu automatycznie wymuszają / konwertują typy.
Na przykład w tym artykule zatytułowanym Typing: Strong vs. Słaby, Static vs. Dynamic mówi, że Python jest silnie wpisywany, ponieważ otrzymasz wyjątek, jeśli spróbujesz:
Pyton
1 + "1"
Traceback (most recent call last):
File "", line 1, in ?
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Jednak coś takiego jest możliwe w Javie i C # i nie uważamy ich za słabo wpisane tylko do tego.
Jawa
int a = 10;
String b = "b";
String result = a + b;
System.out.println(result);
DO#
int a = 10;
string b = "b";
string c = a + b;
Console.WriteLine(c);
W tym innym artykule, zatytułowanym Weakly Type Languages, autor mówi, że Perl jest napisany słabo po prostu dlatego, że mogę połączyć ciąg z liczbą i odwrotnie bez żadnej wyraźnej konwersji.
Perl
$a=10;
$b="a";
$c=$a.$b;
print $c; #10a
Więc ten sam przykład sprawia, że Perl jest słabo typizowany, ale nie Java i C # ?.
Ojej, to jest mylące
Autorzy zdają się sugerować, że język, który uniemożliwia stosowanie pewnych operacji na wartościach różnych typów, jest silnie typizowany, a przeciwnie - słabo typizowany.
Dlatego w pewnym momencie poczułem się skłonny uwierzyć, że jeśli język zapewnia wiele automatycznych konwersji lub przymusu między typami (jak perl), może zostać uznany za słabo napisany, podczas gdy inne języki, które zapewniają tylko kilka konwersji, mogą skończyć się uważane za silnie wpisane.
Jestem jednak skłonny wierzyć, że w tej interpretacji muszę się mylić, po prostu nie wiem dlaczego ani jak to wyjaśnić.
Tak więc moje pytania to:
- Co to naprawdę oznacza, że język jest naprawdę słabo napisany?
- Czy mógłbyś wymienić jakieś dobre przykłady słabego pisania, które nie są związane z automatyczną konwersją / automatycznym przymusem wykonywanym przez język?
- Czy język może być słabo i silnie wpisany w tym samym czasie?
Odpowiedzi:
AKTUALIZACJA: To pytanie było tematem mojego bloga 15 października 2012. Dzięki za świetne pytanie!
To znaczy „ten język używa systemu typów, który uważam za niesmaczny”. Natomiast język „silnie wpisany” to język z systemem typów, który wydaje mi się przyjemny.
Terminy są zasadniczo bez znaczenia i należy ich unikać. Wikipedia wymienia jedenaście różnych znaczeń wyrażenia „silnie wpisany”, z których kilka jest sprzecznych. Oznacza to, że prawdopodobieństwo pomyłki jest wysokie w każdej rozmowie, w której występuje termin „mocno wpisany” lub „napisany słabo”.
Wszystko, co możesz naprawdę powiedzieć z całą pewnością, to to, że omawiany język „silnie typowany” ma pewne dodatkowe ograniczenia w systemie typów, zarówno w czasie wykonywania, jak i kompilacji, których brakuje w omawianym języku „słabo typizowanym”. Bez dalszego kontekstu nie można określić, czym to ograniczenie może być.
Zamiast używać „silnie wpisanych” i „słabo wpisanych”, powinieneś szczegółowo opisać, jaki rodzaj bezpieczeństwa typów masz na myśli. Na przykład, C # jest statycznie wpisane język i bezpieczny rodzaj języka i bezpieczna pamięć język, w przeważającej części. C # pozwala na naruszenie wszystkich trzech form „silnego” pisania. Operator rzutowania narusza statyczne typowanie; mówi do kompilatora "Wiem więcej o typie środowiska wykonawczego tego wyrażenia niż ty". Jeśli deweloper się pomyli, środowisko uruchomieniowe zgłosi wyjątek w celu ochrony bezpieczeństwa typu. Jeśli twórca chce złamać bezpieczeństwo typu lub bezpieczeństwo pamięci, może to zrobić, wyłączając system bezpieczeństwa typu, tworząc „niebezpieczny” blok. W niebezpiecznym bloku możesz użyć magii wskaźnika, aby traktować int jako zmiennoprzecinkowy (narusza bezpieczeństwo typów) lub zapisywać do pamięci, której nie jesteś właścicielem. (Naruszenie bezpieczeństwa pamięci.)
C # nakłada ograniczenia typu, które są sprawdzane zarówno w czasie kompilacji, jak i w czasie wykonywania, dzięki czemu jest to język „silnie typizowany” w porównaniu z językami, które wykonują mniej kontroli w czasie kompilacji lub mniej w czasie wykonywania. C # pozwala również w szczególnych okolicznościach obejść te ograniczenia, czyniąc go językiem „słabo typizowanym” w porównaniu z językami, które nie pozwalają na takie zakończenie.
Co to naprawdę jest? Nie można powiedzieć; zależy to od punktu widzenia mówiącego i jego stosunku do różnych cech języka.
źródło
Jak zauważyli inni, terminy „mocno wpisane” i „słabo wpisane” mają tak wiele różnych znaczeń, że nie ma jednej odpowiedzi na Twoje pytanie. Jednakże, ponieważ w swoim pytaniu wyraźnie wspomniałeś o Perlu, spróbuję wyjaśnić, w jakim sensie Perl jest napisany słabo.
Chodzi o to, że w Perlu nie ma czegoś takiego jak „zmienna całkowita”, „zmienna typu float”, „zmienna łańcuchowa” czy „zmienna boolowska”. W rzeczywistości, o ile użytkownik może (zazwyczaj) powiedzieć, że nie ma nawet całkowitą, pływak, ciąg lub wartość logiczna wartości : wszystko co musisz to „skalary”, które są wszystkie te rzeczy jednocześnie. Możesz więc na przykład napisać:
Oczywiście, jak słusznie zauważyłeś, wszystko to można postrzegać jako wymuszenie typu. Ale chodzi o to, że w Perlu typy są zawsze wymuszane. W rzeczywistości użytkownikowi trudno jest określić, jaki może być wewnętrzny „typ” zmiennej: w linii 2 w powyższym przykładzie pytanie, czy wartość
$bar
jest ciągiem,"9"
czy liczbą,9
jest prawie bez znaczenia, ponieważ jeśli chodzi o Perla, to jest to samo . Rzeczywiście, jest nawet możliwe, aby skalar Perla miał wewnętrznie zarówno ciąg znaków, jak i wartość liczbową w tym samym czasie, jak ma to miejsce na przykład w przypadku$foo
po linii 2 powyżej.Odwrotną stroną tego wszystkiego jest to, że ponieważ zmienne Perla nie mają określonego typu (lub raczej nie ujawniają swojego typu wewnętrznego użytkownikowi), operatory nie mogą być przeciążane, aby robić różne rzeczy dla różnych typów argumentów; nie możesz po prostu powiedzieć „ten operator zrobi X dla liczb i Y dla łańcuchów”, ponieważ operator nie może (nie) powiedzieć, jakiego rodzaju wartości są jego argumenty.
Na przykład Perl ma i potrzebuje zarówno liczbowego operatora dodawania (
+
), jak i operatora konkatenacji ciągów (.
): jak widzieliśmy powyżej, dodawanie łańcuchów ("1" + "2" == "3"
) lub łączenie liczb (1 . 2 == 12
) jest całkowicie w porządku . Podobnie liczbowe operatory porównania==
,!=
,<
,>
,<=
,>=
i<=>
porównać wartości numerycznych swoich argumentów, a operatory porównania ciągeq
,ne
,lt
,gt
,le
,ge
icmp
porównać je leksykograficznie jako ciągi. Tak2 < 10
, ale2 gt 10
(ale"02" lt 10
, podczas gdy"02" == 2
). (Pamiętaj, że niektóre inne języki, takie jak JavaScript, starają się dostosować do pisania w Perlu słaberównież przeciąża operatora. Często prowadzi to do brzydoty, takiej jak utrata skojarzeń+
).(Mucha w maści polega na tym, że ze względów historycznych Perl 5 ma kilka przypadków narożnych, takich jak bitowe operatory logiczne, których zachowanie zależy od wewnętrznej reprezentacji ich argumentów. Są one ogólnie uważane za irytującą wadę projektową, ponieważ reprezentacja wewnętrzna może się zmienić z zaskakujących powodów, więc przewidywanie, co te operatory robią w danej sytuacji, może być trudne).
Wszystko powiedziane, że można argumentować, że Perl ma mieć silne typy; po prostu nie są typami, których można by się spodziewać. W szczególności, oprócz omówionego powyżej typu „skalarnego”, Perl ma również dwa typy strukturalne: „tablicę” i „hasz”. Są one bardzo różne od skalarów, do tego stopnia, że zmienne Perla mają różne sigile wskazujące na ich typ (
$
dla skalarów,@
dla tablic,%
dla skrótów) 1 . Tam są zasady przymusu między tymi typami, więc można napisać na przykład%foo = @bar
, ale wiele z nich jest bardzo stratny: na przykład,$foo = @bar
przypisuje długość tablicy@bar
do$foo
, a nie jego zawartość. (Istnieje również kilka innych dziwnych typów, takich jak typeglobs i uchwyty I / O, których często nie widać.)Niewielką luką w tym ładnym projekcie jest również istnienie typów referencyjnych, które są szczególnym rodzajem skalarów (i które można odróżnić od zwykłych skalarów za pomocą
ref
operatora). Możliwe jest użycie odniesień jako normalnych skalarów, ale ich wartości łańcuchowe / numeryczne nie są szczególnie przydatne i mają tendencję do tracenia specjalnego odniesienia, jeśli zmodyfikujesz je za pomocą normalnych operacji skalarnych. Ponadto każdą zmienną Perla 2 można przypisaćbless
do klasy, zamieniając ją w obiekt tej klasy; system klas OO w Perlu jest nieco ortogonalny w stosunku do opisanego powyżej systemu typów pierwotnych (lub beztypu), chociaż jest również „słaby” w sensie pisania kaczegoparadygmat. Ogólna opinia jest taka, że jeśli stwierdzisz, że sprawdzasz klasę obiektu w Perlu, robisz coś złego.1 Właściwie pieczęć oznacza typ wartości są dostępne, tak że na przykład pierwsza skalarne w tablicy
@foo
jest oznaczona$foo[0]
. Więcej szczegółów znajdziesz w perlfaq4 .2 Obiekty w Perlu są (normalnie) dostępne poprzez odniesienia do nich, ale to, co faktycznie jest
bless
edytowane, to (prawdopodobnie anonimowa) zmienna, na którą wskazuje odniesienie. Jednak błogosławieństwo jest rzeczywiście właściwością zmiennej, a nie jej wartością, więc np. Przypisanie rzeczywistej błogosławionej zmiennej do innej daje tylko jej płytką, nie pobłogosławioną kopię. Więcej informacji znajdziesz w perlobj .źródło
Oprócz tego, co powiedział Eric, rozważ następujący kod C:
W przeciwieństwie do języków takich jak Python, C #, Java lub inne, powyższe jest słabo wpisane, ponieważ tracimy informacje o typie. Eric poprawnie wskazał, że w C # możemy obejść kompilator poprzez rzutowanie, skutecznie mówiąc mu „Wiem więcej o typie tej zmiennej niż ty”.
Ale nawet wtedy środowisko wykonawcze nadal będzie sprawdzać typ! Jeśli rzutowanie jest nieprawidłowe, system wykonawczy przechwyci go i zgłosi wyjątek.
W przypadku wymazywania typów tak się nie dzieje - informacje o typach są wyrzucane. Rzut do
void*
w C robi dokładnie to. Pod tym względem powyższe różni się zasadniczo od deklaracji metody C #, takiej jakvoid f(Object x)
.(Z technicznego punktu widzenia C # umożliwia również usuwanie typów za pomocą niebezpiecznego kodu lub kierowania).
To jest tak słabo wpisane, jak to tylko możliwe. Cała reszta to tylko kwestia statycznego i dynamicznego sprawdzania typu, tj. Czasu, w którym typ jest sprawdzany.
źródło
void*
przerywa sprawdzanie obu typów. Wymazywanie typu ogólnego tego nie robi, omija tylko sprawdzanie czasu kompilacji. Pod tym względem jest dokładnie tak, jak wyraźne odlewy (wspomniane przez Erica).Doskonały przykład pochodzi z artykułu Strong Typing na Wikipedii :
Generalnie silne typowanie oznacza, że język programowania nakłada poważne ograniczenia na mieszanie, które jest dozwolone.
Słabe pisanie
Silne pisanie
Zwróć uwagę, że słaby język pisania na klawiaturze może łączyć różne typy bez błędów. Silny język typów wymaga, aby typy wejściowe były oczekiwanymi typami. W silnym języku typów typ można konwertować (
str(a)
konwertuje liczbę całkowitą na łańcuch) lub cast (int(b)
).Wszystko zależy od interpretacji pisania.
źródło
Chciałbym wnieść swój wkład do dyskusji własnymi badaniami na ten temat, ponieważ inni komentują i wnoszą swój wkład. Czytałem ich odpowiedzi i śledziłem ich odniesienia i znalazłem interesujące informacje. Jak zasugerowano, jest prawdopodobne, że większość z nich byłaby lepiej omówiona na forum programistów, ponieważ wydaje się być bardziej teoretyczna niż praktyczna.
Z teoretycznego punktu widzenia myślę, że artykuł Luca Cardellego i Petera Wegnera zatytułowany O zrozumieniu typów, abstrakcji danych i polimorfizmie zawiera jeden z najlepszych argumentów, jakie przeczytałem.
To stwierdzenie wydaje się sugerować, że słabe pisanie pozwoliłoby nam uzyskać dostęp do wewnętrznej struktury typu i manipulować nim tak, jakby był czymś innym (innym typem). Być może co moglibyśmy zrobić z niebezpiecznym kodem (wspomnianym przez Erica) lub ze wskaźnikami wymazanymi przez typ c, o których wspomniał Konrad.
Artykuł jest kontynuowany ...
Jako takie, mocne pisanie oznacza brak błędów typowych, mogę tylko założyć, że słabe pisanie oznacza coś przeciwnego: prawdopodobną obecność błędów. W czasie wykonywania czy kompilacji? Wydaje się tu nieistotne.
Zabawne, zgodnie z tą definicją język z potężnymi wymuszeniami typów, jak Perl, byłby uważany za silnie wpisany na typ, ponieważ system nie zawodzi, ale radzi sobie z typami, zmuszając je do odpowiednich i dobrze zdefiniowanych odpowiedników.
Z drugiej strony, można powiedzieć niż naddatkiem
ClassCastException
iArrayStoreException
(w Javie) iInvalidCastException
,ArrayTypeMismatchException
(w języku C #) wskazywałoby na poziom słabo pisania, przynajmniej w czasie kompilacji? Odpowiedź Erica wydaje się zgadzać z tym.W drugim artykule zatytułowanym Programowanie typowe, zawartym w jednym z odnośników podanych w jednej z odpowiedzi na to pytanie, Luca Cardelli zagłębia się w koncepcję naruszeń typów:
W związku z tym wymuszenia typu, takie jak te dostarczane przez operatorów, mogą być uważane za naruszenia typów, ale jeśli nie naruszają spójności systemu typów, możemy powiedzieć, że nie prowadzą do słabo typowanego systemu.
Na tej podstawie ani Python, Perl, Java ani C # nie są słabo wpisane.
Cardelli wspomina o dwóch typach wulgaryzmów, które bardzo dobrze rozważam w przypadkach naprawdę słabego pisania:
Tego rodzaju rzeczy możliwe w językach takich jak C (wspomniane przez Konrada) lub przez niebezpieczny kod w .Net (wspomniane przez Erica) naprawdę oznaczałyby słabe pisanie.
Uważam, że jak dotąd najlepszą odpowiedzią jest Eric, ponieważ definicja tych pojęć jest bardzo teoretyczna, a jeśli chodzi o konkretny język, interpretacja wszystkich tych koncepcji może prowadzić do różnych dyskusyjnych wniosków.
źródło
Słabe typowanie rzeczywiście oznacza, że wysoki procent typów może być niejawnie wymuszony, próbując odgadnąć, co zamierzał koder.
Silne pisanie oznacza, że typy nie są wymuszane lub przynajmniej wymuszane mniej.
Typowanie statyczne oznacza, że typy zmiennych są określane w czasie kompilacji.
Wiele osób myliło ostatnio „wyraźnie wpisane” z „wyraźnie wpisane na maszynie”. „Manifestly typed” oznacza, że jawnie deklarujesz typy zmiennych.
Python jest przeważnie silnie typizowany, chociaż możesz użyć prawie wszystkiego w kontekście logicznym, a logiczne mogą być używane w kontekście liczb całkowitych, a możesz użyć liczby całkowitej w kontekście zmiennoprzecinkowym. Nie jest jawnie wpisany, ponieważ nie musisz deklarować swoich typów (z wyjątkiem Cythona, który nie jest całkowicie Python, aczkolwiek interesujący). Nie jest również wpisywany statycznie.
C i C ++ są wyraźnie wpisywane, typowane statycznie i nieco silnie typowane, ponieważ deklarujesz swoje typy, typy są określane w czasie kompilacji i możesz mieszać liczby całkowite i wskaźniki lub liczby całkowite i podwójne, a nawet rzutować wskaźnik do jednego typu na wskaźnik do innego typu.
Haskell jest interesującym przykładem, ponieważ nie jest wyraźnie wpisany, ale jest również wpisany statycznie i silnie.
źródło
Silne <=> słabe typowanie dotyczy nie tylko kontinuum tego, ile lub jak mało wartości jest automatycznie wymuszanych przez język dla jednego typu danych na inny, ale także tego, jak mocno lub słabo wpisywane są rzeczywiste wartości . W Pythonie i Javie, a głównie w C #, wartości mają swoje typy ustawione w kamieniu. W Perlu nie tak bardzo - tak naprawdę jest tylko kilka różnych typów wartości, które można przechowywać w zmiennej.
Otwórzmy po kolei skrzynki.
Pyton
Na przykład Python
1 + "1"
,+
operator wywołuje__add__
na typint
nadając mu ciąg"1"
jako argument - Powoduje to jednak w NotImplemented:Następnie interpreter próbuje
__radd__
z str:Ponieważ się nie powiedzie,
+
operator zawodzi z wynikiemTypeError: unsupported operand type(s) for +: 'int' and 'str'
. Jako taki, wyjątek nie mówi wiele o silnym typowaniu, ale fakt, że operator+
nie wymusza automatycznie swoich argumentów na ten sam typ, wskazuje na fakt, że Python nie jest najsłabiej typizowanym językiem w kontinuum.Z drugiej strony, w Pythonie
'a' * 5
jest realizowany:To jest,
Fakt, że operacja jest inna, wymaga pewnego silnego typowania - jednak przeciwieństwo
*
przekształcania wartości na liczby przed pomnożeniem nadal niekoniecznie powodowałoby, że wartości byłyby słabo typowane.Jawa
Przykład w Javie
String result = "1" + 1;
działa tylko dlatego, że dla wygody operator+
jest przeciążony ciągami.+
Operator Java zastępuje sekwencję utworzeniemStringBuilder
(zobacz to ):Jest to raczej przykład bardzo statycznego pisania bez rzeczywistego przymusu -
StringBuilder
ma metodę,append(Object)
która jest tutaj specjalnie używana. Dokumentacja mówi, co następuje:Gdzie
String.valueOf
wtedyJest to zatem przypadek absolutnego braku przymusu ze strony języka - delegowanie wszelkich trosk na same przedmioty.
DO#
Według odpowiedzi Jona Skeeta , operator
+
nie jest nawet przeciążony dlastring
klasy - podobnie jak w Javie, jest to po prostu wygoda generowana przez kompilator, dzięki zarówno statycznemu, jak i silnemu typowaniu.Perl
Jak wyjaśnia perldata ,
Perl nie ma jednak oddzielnego typu danych dla liczb, wartości logicznych, łańcuchów, wartości null,
undefined
s, odniesień do innych obiektów itp. - ma tylko jeden typ dla wszystkich tych obiektów, typ skalarny; 0 jest wartością skalarną równą „0”. Zmienna skalarna , która została ustawiona jako ciąg znaków, może naprawdę zmienić się w liczbę i od tego momentu zachowywać się inaczej niż „zwykły łańcuch”, jeśli jest dostępna w kontekście numerycznym. Skalar może pomieścić wszystko w Perlu, jest to tyle samo obiektu, ile istnieje w systemie. podczas gdy w Pythonie nazwy odnoszą się tylko do obiektów, w Perlu wartości skalarne w nazwach są obiektami zmiennymi. Co więcej, do tego przyklejony jest system Object Oriented Type: w perlu są tylko 3 typy danych - skalary, listy i hashe. Obiekt zdefiniowany przez użytkownika w Perlu jest odniesieniem (czyli wskaźnikiem do dowolnego z 3 poprzednich)bless
pakietów - możesz wziąć dowolną taką wartość i pobłogosławić ją dowolnej klasie w dowolnym momencie.Perl pozwala nawet na zmianę klas wartości według kaprysu - nie jest to możliwe w Pythonie, gdzie aby utworzyć wartość jakiejś klasy, musisz jawnie skonstruować wartość należącą do tej klasy
object.__new__
lub podobną. W Pythonie nie da się tak naprawdę zmienić istoty obiektu po utworzeniu, w Perlu możesz zrobić wiele:w ten sposób tożsamość typu jest słabo związana ze zmienną i można ją zmienić za pomocą dowolnego odwołania w locie. W rzeczywistości, jeśli to zrobisz
\$another
nie ma tożsamości klasowej, mimo że\$val
nadal będzie stanowić błogosławione odniesienie.TL; DR
W Perlu jest o wiele więcej niż tylko automatyczne wymuszanie, ale chodzi o to, że same typy wartości nie są utrwalone, w przeciwieństwie do Pythona, który jest dynamicznym, ale bardzo silnie typizowanym językiem. Że pyton daje
TypeError
na1 + "1"
to wskazuje, że język jest silnie wpisany, choć wbrew jeden robi coś pożytecznego, jak w Java lub C # nie wyklucza je jako zdecydowanie wpisywanych języków.źródło
Jak wielu innych wyraziło, całe pojęcie „silnego” i „słabego” pisania jest problematyczne.
Jako archetyp Smalltalk jest bardzo silnie wpisany - zawsze zgłosi wyjątek, jeśli operacja między dwoma obiektami jest niekompatybilna. Jednak podejrzewam, że niewielu na tej liście nazwałoby Smalltalk językiem z silną typizacją, ponieważ jest on wpisywany dynamicznie.
Uważam, że pojęcie „statyczne” i „dynamiczne” typowanie jest bardziej przydatne niż „mocne” i „słabe”. Język z typowaniem statycznym ma wszystkie typy wyliczone w czasie kompilacji, a programista musi jawnie zadeklarować, jeśli jest inaczej.
Porównaj z językiem dynamicznie wpisywanym, w którym pisanie jest wykonywane w czasie wykonywania. Jest to zazwyczaj wymagane w przypadku języków polimorficznych, więc programista nie musi z góry decydować o tym, czy operacja między dwoma obiektami jest legalna.
W językach polimorficznych, z typami dynamicznymi (jak Smalltalk i Ruby), bardziej przydatne jest myślenie o „typie” jako o „zgodności z protokołem”. Jeśli obiekt jest zgodny z protokołem w taki sam sposób, jak inny obiekt - nawet jeśli te dwa obiekty nie mają wspólnego dziedziczenia, mixinów ani innego voodoo - są uznawane przez system wykonawczy za ten sam „typ”. Mówiąc dokładniej, obiekt w takich systemach jest autonomiczny i może zdecydować, czy ma sens odpowiadać na jakąkolwiek konkretną wiadomość odnoszącą się do konkretnego argumentu.
Chcesz obiektu, który może dać sensowną odpowiedź na komunikat „+” z argumentem obiektu opisującym kolor niebieski? Możesz to zrobić w językach z dynamicznym typowaniem, ale jest to uciążliwe w przypadku języków z typowaniem statycznym.
źródło
Podoba mi się odpowiedź @Erica Lipperta , ale aby odpowiedzieć na to pytanie - języki silnie typowane zazwyczaj mają wyraźną wiedzę o typach zmiennych w każdym punkcie programu. Języki słabo typowane tego nie robią, więc mogą próbować wykonać operację, która może nie być możliwa dla określonego typu. Wydaje się, że najłatwiej to zobaczyć w funkcji. C ++:
a
Wiadomo, że zmienna jest typu string i każda niezgodna operacja zostanie przechwycona w czasie kompilacji.Pyton:
Zmienna
a
może być dowolna i możemy mieć kod, który wywołuje nieprawidłową metodę, która zostanie przechwycona tylko w czasie wykonywania.źródło