Smalltalk

programozási nyelv

A Smalltalk egy objektumorientált, dinamikusan tipizált, reflektív programozási nyelv. A Smalltalkot az "ember-számítógép szimbiózis" által példázott "új számítástechnikai világ" alapnyelveként hozták létre. A nyelvet részben oktatási célokra, különösen a konstruktivista tanuláshoz tervezték és hozták létre a Xerox PARC Learning Research Group (LRG) munkatársai, Alan Kay, Dan Ingalls, Adele Goldberg, Ted Kaehler, Diana Merry, Scott Wallace és mások az 1970-es években.

A nyelv először Smalltalk-80 néven jelent meg. A Smalltalk-szerű nyelveket aktívan fejlesztik, és hűséges felhasználói közösségeket gyűjtöttek maguk köré. Az ANSI Smalltalkot 1998-ban ratifikálták, és ez a Smalltalk szabványos változata.[1]

A Smalltalk 2017-ben a Stack Overflow fejlesztői felmérésében a második helyet szerezte meg a "legkedveltebb programozási nyelv" kategóriában, de a 2018-as felmérésben nem került be a 26 legkedveltebb programozási nyelv közé.[2]

Történelem szerkesztés

Számos Smalltalk változat létezik. A Smalltalk szóval gyakran jelölik a Smalltalk-80 nyelvet, az első nyilvánosan elérhetővé tett változatot, amelyet 1980-ban készítettek. Az első hardver-környezetek, amelyeken a Smalltalk VM-ek futottak, Xerox Alto számítógépek voltak.

A Smalltalk a Xerox Palo Alto Research Center (PARC) Alan Kay által vezetett kutatásának eredménye; Alan Kay tervezte a korai Smalltalk-verziók nagy részét, Adele Goldberg írta a dokumentáció nagy részét, Dan Ingalls pedig a korai verziók nagy részét implementálta. Az első, Smalltalk-71 elnevezésű verziót Kay néhány reggel alatt készítette el egy fogadásból, hogy a Simula által inspirált üzenetátadás ötletén alapuló programozási nyelvet "egy oldalnyi kódban" meg lehet valósítani. Egy későbbi, kutatómunkához használt változatot Smalltalk-72-nek neveztek el, és befolyásolta az Actor-modell kialakulását. Szintaxisa és végrehajtási modellje nagyban különbözött a modern Smalltalk-változatoktól.

Jelentős átdolgozások után, amelyek a teljesítmény növelése érdekében a végrehajtás szemantikájának néhány aspektusát befagyasztották (egy Simula-szerű osztály öröklési modell bevezetésével), létrejött a Smalltalk-76. Ez a rendszer egy olyan fejlesztőkörnyezettel rendelkezett, amely a ma már megszokott eszközök többségét tartalmazta, beleértve az osztálykönyvtár kódböngészőjét/szerkesztőjét is. A Smalltalk-80 metaosztályokkal egészült ki, hogy segítsen fenntartani a "minden egy objektum" paradigmát (kivéve a privát példányváltozókat) azáltal, hogy tulajdonságokat és viselkedést társított az egyes osztályokhoz, sőt olyan primitíveket is, mint az egész és bólus értékek (például a példányok létrehozásának különböző módjainak támogatására).

Jelentős átdolgozások után, amelyek a teljesítmény növelése érdekében a végrehajtás szemantikájának néhány aspektusát befagyasztották (egy Simula-szerű osztály öröklési modell bevezetésével), létrejött a Smalltalk-76. Ez a rendszer egy olyan fejlesztőkörnyezettel rendelkezett, amely a ma már megszokott eszközök többségét tartalmazta, beleértve az osztálykönyvtár kódböngészőjét/szerkesztőjét is. A Smalltalk-80 metaosztályokkal egészült ki, hogy segítsen fenntartani a "minden egy objektum" paradigmát (kivéve a privát példányváltozókat) azáltal, hogy tulajdonságokat és viselkedést társított az egyes osztályokhoz, sőt olyan primitíveket is, mint az egész és bólus értékek (például a példányok létrehozásának különböző módjainak támogatására).

A jelenleg népszerű Smalltalk implementációs változatok közül kettő az eredeti Smalltalk-80-as képek leszármazottja. A Squeak egy nyílt forráskódú implementáció, amely a Smalltalk-80 1. verziójából származik az Apple Smalltalk segítségével. A VisualWorks a Smalltalk-80 2. verziójából származik a Smalltalk-80 2.5 és az ObjectWorks segítségével (mindkettő a ParcPlace Systems terméke, amely a Xerox PARC spin-off cége, amelyet a Smalltalk piacra dobására hoztak létre). A generációk közötti érdekes kapcsolódási pontként Vassili Bykov 2001-ben megvalósította a Hobbes-t, egy virtuális gépet, amely Smalltalk-80-at futtat a VisualWorks-en belül. (Dan Ingalls később a Hobbes-t Squeak-re portolta).

Az 1980-as évek végétől az 1990-es évek közepéig a Smalltalk-környezeteket – beleértve a támogatást, a képzést és a kiegészítőket – két egymással versengő szervezet értékesítette: ParcPlace Systems és Digitalk, mindkettő kaliforniai székhelyű. A ParcPlace Systems inkább a Unix/Sun mikrorendszerek piacára összpontosított, míg a Digitalk a Microsoft Windows-t vagy az IBM OS/2-t futtató Intel-alapú PC-kre. A Smalltalk jelentős memóriaigénye, korlátozott futási teljesítménye és az SQL-alapú relációs adatbázis-kiszolgálókhoz való támogatott kapcsolódás kezdeti hiánya miatt mindkét cégnek nehézséget okozott a Smalltalk elterjedése. Míg a ParcPlace Smalltalk magas ára a piaci elterjedését a közepes és nagy kereskedelmi szervezetekre korlátozta, a Digitalk termékek kezdetben alacsonyabb árral próbáltak szélesebb közönséget elérni. Az IBM kezdetben támogatta a Digitalk terméket, de aztán 1995-ben belépett a piacra egy Smalltalk termékkel, a VisualAge/Smalltalkkal. Az Easel ebben az időben vezette be az Enfin-t Windows és OS/2 rendszereken. Az Enfin sokkal népszerűbb lett Európában, mivel az IBM még az IBM Smalltalk (később VisualAge) kifejlesztése előtt bevezette az informatikai boltokba. Az Enfin-t később felvásárolta a Cincom Systems, és ma ObjectStudio néven árulják, és a Cincom Smalltalk termékcsomagjának része.

1995-ben a ParcPlace és a Digitalk ParcPlace-Digitalk néven egyesült, majd 1997-ben ObjectShare néven újjáalakult, székhelye Irvine, Kalifornia. Az ObjectShare (NASDAQ: OBJS) 1999-ig nyilvánosan volt jegyezve, amikor kivonták a tőzsdéről és megszűnt. A beolvadt cégnek soha nem sikerült hatékony választ találnia a Javára a piaci pozícionálást illetően, és 1997-ben a tulajdonosok már el akarták adni az üzletágat. 1999-ben a Seagull Software felvásárolta az ObjectShare Java fejlesztő laboratóriumát (beleértve az eredeti Smalltalk/V és Visual Smalltalk fejlesztőcsapatot), és még mindig a VisualSmalltalk tulajdonosa, bár a Smalltalk termék világméretű forgalmazási jogai az ObjectShare-nél maradtak, amely aztán eladta azokat a Cincomnak. A VisualWorks-et eladták a Cincomnak, és most a Cincom Smalltalk része. A Cincom erőteljesen támogatta a Smalltalkot, 1999 óta minden évben több új verziót ad ki a VisualWorks és az ObjectStudio programból.

A Cincom, a GemTalk és az Instantiations továbbra is Smalltalk-környezeteket forgalmaz. Az IBM a VisualAge Smalltalkot "leállította", miután az 1990-es évek végén úgy döntött, hogy inkább a Java-t támogatja, és 2005-től az Instantiations, Inc. támogatja, akik átnevezték a terméket VA Smalltalkra (VAST Platform), és továbbra is évente új verziókat adnak ki. A nyílt Squeak implementációnak aktív fejlesztői közössége van, köztük sokan az eredeti Smalltalk közösségből, és a közelmúltban az OLPC projekt Etoys környezetének, a Croquet Project kollaboratív alkalmazások fejlesztésére szolgáló eszközkészletnek és az Open Cobalt virtuális világ alkalmazásnak a biztosításához használták. A GNU Smalltalk a GNU projekt Smalltalk-80 származékának szabad szoftveres implementációja. A Pharo Smalltalk a Squeak elágazása, amely a kutatásra és a kereskedelmi környezetben való használatra irányul.

Jelentős fejlemény, amely 2016-tól minden Smalltalk-környezetben elterjedt, a két webes keretrendszer, a Seaside és az AIDA/Web egyre szélesebb körű használata a komplex webes alkalmazások építésének egyszerűsítése érdekében. A Seaside iránt jelentős piaci érdeklődés mutatkozott, a Cincom, a Gemstone és az Instantiations beépítette és kibővítette.

Befolyások szerkesztés

A Smalltalk egyike volt a Simulán alapuló objektumorientált programozási nyelveknek. A Smalltalk egyben az egyik legnagyobb hatású programozási nyelv is. Gyakorlatilag az összes objektumorientált nyelv, amely utána jött – a Flavors, a CLOS, az Objective-C, a Java, a Python, a Ruby és sok más – a Smalltalk hatása alatt állt. A Smalltalk volt az egyik legnépszerűbb nyelv az agilis szoftverfejlesztési módszerek, a gyors alkalmazásfejlesztés (RAD) vagy prototípusok készítése és a szoftvertervezési minták terén is. A Smalltalk platformok által biztosított rendkívül produktív környezet ideális volt a gyors, iteratív fejlesztéshez.

A Smalltalk egy nagyobb, az Advanced Research Projects Agency (ARPA) által finanszírozott kutatási programból nőtt ki, amely sok szempontból meghatározta a modern számítástechnika világát. A Smalltalk mellett az ARPA kutatói az 1960-as években olyan dolgok működő prototípusait fejlesztették ki, mint a hipertext, a grafikus felhasználói felület, a multimédia, az egér, a távjelenlét és az internet. Alan Kay (a Smalltalk egyik feltalálója) egy általa Dynabooknak nevezett táblagépet is leírt, amely hasonlít a modern táblagépekhez, például az iPadhez.[3]

A Smalltalk-környezetek gyakran elsőként fejlesztették ki a ma már elterjedt objektumorientált szoftvertervezési mintákat. Az egyik legnépszerűbb a modell-nézet-vezérlő (MVC) minta a felhasználói felület tervezéséhez. Az MVC-minta lehetővé teszi a fejlesztők számára, hogy ugyanazon mögöttes adatokra több konzisztens nézetet alakítsanak ki. Ideális olyan szoftverfejlesztési környezetekben, ahol ugyanannak a mögöttes specifikációnak különböző nézetei vannak (pl. entitás-reláció, adatfolyam, objektummodell stb.). Továbbá szimulációkhoz vagy játékokhoz, ahol a mögöttes modell különböző nézőpontokból és absztrakciós szintekről nézhető.[4]

Az MVC mintán kívül a Smalltalk nyelv és környezet nagy hatással volt a grafikus felhasználói felület (GUI) és a WYSIWYG (what you see is what you get) felhasználói felület, a betűszerkesztők és a felhasználói felület tervezésének asztali metaforái történetére. A Smalltalk-környezetekhez tartozó hatékony beépített hibakeresési és objektumvizsgálati eszközök meghatározták a szabványt az összes utána következő integrált fejlesztőkörnyezet számára, kezdve a Lisp Machine környezetekkel.[5]

Objektumorientált programozás szerkesztés

 

Más objektumorientált nyelvekhez hasonlóan a Smalltalk-80-ban (de nem a Smalltalk-72-ben) is az objektum a központi fogalom. Az objektum mindig egy osztály példánya. Az osztályok "tervrajzok", amelyek leírják példányaik tulajdonságait és viselkedését. Például egy GUI ablak osztálya deklarálhatja, hogy az ablakok rendelkeznek olyan tulajdonságokkal, mint a címke, a pozíció és az, hogy az ablak látható-e vagy sem. Az osztály azt is deklarálhatja, hogy a példányok támogatják az olyan műveleteket, mint a nyitás, zárás, mozgatás és elrejtés. Minden egyes ablakobjektumnak saját értékei lennének ezekre a tulajdonságokra, és mindegyikük képes lenne az osztálya által meghatározott műveletek végrehajtására.

Egy Smalltalk objektum pontosan három dologra képes:

  1. Hold állapot (hivatkozások más objektumokra).
  2. Üzenet fogadása önmagától vagy egy másik objektumtól.
  3. Az üzenet feldolgozása során üzeneteket küldhet magának vagy egy másik objektumnak.

Egy objektum állapota mindig az adott objektum sajátja. Más objektumok csak úgy kérdezhetik le vagy változtathatják meg ezt az állapotot, ha erre vonatkozó kéréseket (üzeneteket) küldenek az objektumnak. Bármilyen üzenet küldhető bármelyik objektumnak: amikor egy üzenet érkezik, a címzett eldönti, hogy az üzenet megfelelő-e. Alan Kay megjegyezte, hogy az objektumokra fordított figyelem ellenére az üzenetküldés a Smalltalk legfontosabb fogalma: "A nagy ötlet az 'üzenetküldés' – erről szól a Smalltalk/Squeak magja (és ez az, amit a Xerox PARC fázisunkban soha nem fejeztünk be teljesen)".[6]

A legtöbb más nyelvtől eltérően a Smalltalk objektumok a rendszer futása közben is módosíthatók. Az élő kódolás és a javítások "menet közbeni" alkalmazása a Smalltalk egyik domináns programozási módszertana, és ez az egyik fő oka a hatékonyságának.

A Smalltalk egy "tiszta" objektumorientált programozási nyelv, ami azt jelenti, hogy a C++-tól és a Javától eltérően nincs különbség az objektumnak minősülő és a primitív típusú értékek között. A Smalltalkban az olyan primitív értékek, mint az egészek, a boolék és a karakterek is objektumok, abban az értelemben, hogy a megfelelő osztályok példányai, és a velük végzett műveletek üzenetek küldésével hívhatók elő. A programozó megváltoztathatja vagy kibővítheti (alosztályozással) a primitív értékeket megvalósító osztályokat, hogy új viselkedést lehessen definiálni a példányaik számára – például új vezérlési struktúrák megvalósítása érdekében -, vagy akár úgy, hogy a meglévő viselkedésük megváltozzon. Ezt a tényt a gyakran hallott "A Smalltalkban minden objektum" kifejezés foglalja össze, amit pontosabban úgy lehetne kifejezni, hogy "minden érték objektum", mivel a változók nem azok.

Mivel minden érték objektum, az osztályok is objektumok. Minden osztály az adott osztály metaosztályának példánya. A meta-osztályok viszont szintén objektumok, és mind a Meta-osztály nevű osztály példányai. A kódblokkok – a Smalltalk módja az anonim függvények kifejezésére – szintén objektumok.[7]

Reflexió szerkesztés

A reflexió egy olyan kifejezés, amelyet az informatikusok olyan szoftverprogramokra alkalmaznak, amelyek képesek saját struktúrájuk, például elemzőfájuk vagy a bemeneti és kimeneti paraméterek adattípusainak vizsgálatára. A reflexió az olyan dinamikus, interaktív nyelvek jellemzője, mint a Smalltalk és a Lisp. A reflexióval rendelkező interaktív programok (akár értelmezettek, akár lefordítottak) fenntartják az összes memórián belüli objektum állapotát, beleértve magát a kódobjektumot is, amelyek a parszolás/fordítás során keletkeznek, és programozottan hozzáférhetők és módosíthatók.

A reflexió szintén a meta-modell tulajdonsága, ahogyan a Smalltalk is. A meta-modell a nyelvet leíró modell, és a fejlesztők a meta-modellt használhatják olyan dolgokra, mint például egy objektum parse-fájának végigjárása, vizsgálata és módosítása, vagy egy bizonyos típusú struktúra összes példányának megtalálása (pl. a meta-modellben a Method osztály összes példánya).

A Smalltalk-80 egy teljesen reflektív rendszer, amelyet Smalltalk-80-ban valósítottak meg. A Smalltalk-80 mind strukturális, mind számítási reflexiót biztosít. A Smalltalk egy strukturálisan reflektív rendszer, amelynek struktúráját a Smalltalk-80 objektumok határozzák meg. A rendszert definiáló osztályok és metódusok szintén objektumok, és teljes mértékben részei annak a rendszernek, amelyet segítenek definiálni. A Smalltalk fordító a szöveges forráskódot metódusobjektumokba, jellemzően a CompiledMethod példányaiba fordítja. Ezeket úgy adjuk hozzá az osztályokhoz, hogy az osztály metódusszótárában tároljuk őket. Az osztályhierarchia osztályokat definiáló része új osztályokat adhat hozzá a rendszerhez. A rendszer az osztályokat és metódusokat létrehozó vagy definiáló Smalltalk-80 kód futtatásával bővül. Ily módon a Smalltalk-80 rendszer egy "élő" rendszer, amely magában hordozza azt a képességet, hogy futás közben bővítse önmagát.

Mivel az osztályok objektumok, olyan kérdéseket lehet feltenni nekik, mint például "milyen metódusokat valósítasz meg?" vagy "milyen mezőket/helyeket/instance változókat definiálsz?". Így az objektumok könnyen vizsgálhatók, másolhatók, (de)szerializálhatók stb. olyan általános kóddal, amely a rendszerben lévő bármely objektumra alkalmazható.[8]

A Smalltalk-80 számítási reflexiót is biztosít, azaz a rendszer számítási állapotának megfigyelését. Az eredeti Smalltalk-80-ból származó nyelvekben egy metódus aktuális aktiválása egy pszeudováltozóval (a hat fenntartott szó egyike), thisContext nevű objektumként érhető el. A thisContext-nek küldött üzenetekkel egy metódus aktiválása olyan kérdéseket tehet fel, mint például "ki küldte nekem ezt az üzenetet". Ezek a lehetőségek lehetővé teszik társrutinok vagy Prolog-szerű visszavezetés megvalósítását a virtuális gép módosítása nélkül. A kivételrendszert is ezzel a lehetőséggel van megvalósítva. Ennek egyik legérdekesebb felhasználása a Seaside webes keretrendszerben van, amely megszabadítja a programozót a webböngésző vissza gombjának bonyolultságától azáltal, hogy folytatásokat tárol minden egyes szerkesztett oldalhoz, és ezek között váltogat, ahogy a felhasználó navigál a weboldalon. A webszerver programozása a Seaside segítségével ezután hagyományosabb programozási stílusban történhet.[9]

Egy példa arra, hogy a Smalltalk hogyan használhatja a reflexiót, a hibakezelési mechanizmus. Amikor egy objektum olyan üzenetet kap, amelyet nem valósít meg, a virtuális gép elküldi az objektumnak a doesNotUnderstand: üzenetet, amelynek argumentuma az üzenet reifikációja. Az üzenet (egy másik objektum, a Message példánya) tartalmazza az üzenet kiválasztóját és az argumentumainak tömbjét. Egy interaktív Smalltalk rendszerben a doesNotUnderstand: alapértelmezett implementációja az, amely egy hibaablakot (Notifier) nyit meg, amely a hibát jelenti a felhasználónak. Ezen és a reflektív lehetőségeken keresztül a felhasználó megvizsgálhatja a hiba előfordulásával kapcsolatos kontextust, átdefiniálhatja a hibás kódot, és folytathatja, mindezt a rendszeren belül, a Smalltalk-80 reflektív lehetőségeinek felhasználásával.[10] [11]

Ha létrehozunk egy olyan osztályt, amely csak a doesNotUnderstand: metódust érti (implementálja), létrehozhatunk egy olyan példányt, amely a doesNotUnderstand: metóduson keresztül el tudja fogni a neki küldött üzeneteket. Az ilyen példányokat transzparens proxyknak nevezzük. Az ilyen proxykat aztán számos eszköz megvalósítására lehet használni, mint például az elosztott Smalltalk, ahol az üzenetek több Smalltalk rendszer között cserélődnek, adatbázis-interfészek, ahol az objektumok átláthatóan hibásodnak ki az adatbázisból, ígéretek, stb. Az elosztott Smalltalk tervezése olyan rendszerekre volt hatással, mint a CORBA.

Szintaxis szerkesztés

A Smalltalk-80 szintaxisa meglehetősen minimalista, mindössze néhány deklaráción és fenntartott szón alapul. Valójában csak hat "kulcsszó" van fenntartva a Smalltalkban: true, false, nil, self, super és thisContext. Ezeket megfelelően pszeudováltozóknak nevezik, olyan azonosítóknak, amelyek követik a változóazonosítókra vonatkozó szabályokat, de olyan kötéseket jelölnek, amelyeket a programozó nem változtathat meg. A true, false és nil pszeudováltozók singleton példányok. self és super egy üzenet címzettjére utalnak egy üzenetre válaszul aktivált metóduson belül, de a super-nek küldött küldemények a metódus definiáló osztályának szuperosztályában keresendők, nem pedig a címzett osztályában, ami lehetővé teszi, hogy az alosztályok metódusai meghívják a szuperosztályok azonos nevű metódusait. thisContext az aktuális aktiválási rekordra utal. Az egyetlen beépített nyelvi konstrukció az üzenetküldés, a hozzárendelés, a metódusvisszatérés és néhány objektum esetében a literális szintaxis. A Smalltalk standard szintaxisa – mivel eredetileg gyermekek számára készült – az angolhoz jobban hasonlít az írásjelek használatára, mint a mainstream kódolási nyelveké. A nyelv többi részét, beleértve a feltételes kiértékelés és az iteráció vezérlési struktúráit is, a beépített konstrukciókon felül a Smalltalk szabványos osztálykönyvtára valósítja meg. (Teljesítményi okokból az implementációk felismerhetnek és különlegesként kezelhetnek néhány ilyen üzenetet; ez azonban csak optimalizálás, és nincs a nyelv szintaxisába beágyazva).

A mondás, miszerint "a Smalltalk szintaktika elfér egy képeslapon", Ralph Johnson egy kódrészletére utal, amely a metódusok összes alapvető szabványos szintaktikai elemét bemutatja:[12]

exampleWithNumber: x
    | y |
    true & false not & (nil isNil) ifFalse: [self halt].
    y := self size + super size.
    #($a #a 'a' 1 1.0)
        do: [ :each |
            Transcript show: (each class name);
                       show: ' '].
    ^x < y

Literálok szerkesztés

A következő példák a Smalltalk-80 metódusokban literális értékként leírható leggyakoribb objektumokat szemléltetik.

Számok. Az alábbi lista néhány lehetőséget mutat be.

42
-42
123.45
1.2345e2
2r10010010
16rA000

Az utolsó két bejegyzés egy bináris és egy hexadecimális szám. Az "r" előtti szám a radix vagy bázis. A bázisnak nem kell kettes hatványnak lennie; például a 36rSMALLTALK egy érvényes szám, amely egyenlő 8073816323270632 decimális számmal. A karakterek írása úgy történik, hogy dollárjelet írunk eléjük:

$A

A karakterláncok szimpla idézőjelek közé zárt karaktersorozatok:

'Hello, world!'

Ha idézőjelet szeretne beilleszteni egy karakterláncba, akkor egy második idézőjellel szüntesse meg az idézőjelet:

'I said, ''Hello, world!'' to them.'

A kettős idézőjeleket nem kell szedni, mivel a szimpla idézőjelek egy karakterláncot határolnak:

'I said, "Hello, world!" to them.'

Két azonos karakterlánc (a karakterláncok akkor egyenlőek, ha minden karakterük azonos) különböző objektumok lehetnek, amelyek a memória különböző helyein helyezkednek el. A karakterláncok mellett a Smalltalknak van egy Symbol nevű karaktersorozat-objektumosztálya is. A szimbólumok garantáltan egyediek – nem lehet két egyenlő szimbólum, amely különböző objektum. Emiatt a szimbólumokat nagyon olcsón lehet összehasonlítani, és gyakran használják őket olyan nyelvi artefaktumokhoz, mint például az üzenetválasztók (lásd alább). A szimbólumokat #-nek írjuk, amelyet egy karakterlánc követ. Például:

#'foo'

Ha a sorozat nem tartalmaz szóközöket vagy írásjeleket, akkor ez a következőképpen is leírható:

#foo

Tömbök:

#(1 2 3 4)

egy négy egész számból álló tömböt definiál. Sok implementáció támogatja a ByteArrays következő szó szerinti szintaxisát:

#[1 2 3 4]

egy négy egész számból álló tömböt definiál. És végül, de nem utolsósorban, blokkok (névtelen függvény literálok)

[... Some smalltalk code...]

A blokkokat a szöveg további részében részletesen ismertetjük.

Sok Smalltalk dialektus további szintaxisokat implementál más objektumokhoz, de a fentiek az összes által támogatott alapvető szintaxisok.

Változó deklarációk szerkesztés

A Smalltalkban általánosan használt kétféle változó a példányváltozók és az ideiglenes változók. Az egyéb változók és a kapcsolódó terminológia az adott implementációtól függ. A VisualWorks például rendelkezik osztálymegosztott változókkal és névtérmegosztott változókkal, míg a Squeak és sok más implementáció rendelkezik osztályváltozókkal, poolváltozókkal és globális változókkal.

A Smalltalkban az ideiglenes változók deklarációi a metóduson belül deklarált változók (lásd alább). A metódus tetején deklaráljuk őket szóközökkel elválasztott és függőleges vonallal körülvett nevek formájában. Például:

| index |

deklarál egy index nevű ideiglenes változót, amely kezdetben a nil értéket tartalmazza. Egy sávon belül több változó is deklarálható:

| index vowels |

két változót deklarál: index és magánhangzók. Minden változó inicializálva van. A változókat nil-re inicializáljuk, kivéve a Strings indexált változóit, amelyeket a null karakterre inicializálunk, vagy a ByteArrays változókat, amelyeket 0-ra inicializálunk.

Hozzárendelés szerkesztés

Egy változónak a ':=' szintaxissal adunk értéket. Tehát:

vowels := 'aeiou'

Az 'aeiou' karakterláncot hozzárendeli a korábban deklarált magánhangzók változóhoz. A karakterlánc egy objektum (a szó szerinti karakterláncok szintaxisa a szimpla idézőjelek közötti karaktersorozat), amelyet a fordító a fordításkor hoz létre.

Az eredeti Parc Place-képen az ⟨_⟩ aláhúzás karakter glifája balra néző ⟨←⟩ nyílként jelent meg (mint az ASCII-kód 1963-as változatában). A Smalltalk eredetileg ezt a balra mutató nyilat fogadta el egyetlen hozzárendelési operátorként. Néhány modern kód még mindig tartalmaz olyan, látszólag aláhúzásnak tűnő pontokat, amelyek hozzárendelésként működnek, visszautalva erre az eredeti használatra. A legtöbb modern Smalltalk implementáció vagy az aláhúzást, vagy a kettőspont-egyenértékű szintaxist fogadja el.

Üzenetek szerkesztés

Az üzenet a Smalltalk legalapvetőbb nyelvi konstrukciója. Még a vezérlési struktúrákat is üzenetküldésként valósítják meg. A Smalltalk alapértelmezés szerint dinamikus küldési és egyszeri küldési stratégiát alkalmaz (szemben a többszörös küldéssel, amelyet néhány más objektumorientált nyelv használ).

A következő példa a 'factorial' üzenetet küldi a 42-es számra:

42 factorial

Ebben a helyzetben a 42 az üzenet fogadója, míg a "factorial" az üzenet kiválasztója. A vevő az üzenetre egy érték (ebben az esetben feltehetően a 42 faktoriálisa) visszaküldésével válaszol. Az üzenet eredménye többek között egy változóhoz rendelhető:

aRatherBigNumber := 42 factorial

A fenti "factorial" egy úgynevezett unáris üzenet, mivel csak egy objektum, a címzett vesz részt benne. Az üzenetek további objektumokat is hordozhatnak argumentumként, az alábbiak szerint:

2 raisedTo: 4

Ebben a kifejezésben két objektum szerepel: a 2 a címzett és a 4 az üzenet argumentuma. Az üzenet eredménye, vagy Smalltalk nyelven szólva a válasznak 16-nak kell lennie. Az ilyen üzeneteket kulcsszavas üzeneteknek nevezzük. Egy üzenetnek több argumentuma is lehet, a következő szintaxissal:

'hello world' indexOf: $o startingAt: 6

amely az "o" karakter indexére válaszol a fogadó karakterláncban, és a keresést a 6. indexről kezdi. Ennek az üzenetnek a szelektorja az "indexOf:startingAt:", amely két darabból, azaz kulcsszóból áll. A kulcsszavak és argumentumok ilyen átfedése a kód olvashatóságát hivatott javítani, mivel az argumentumokat az őket megelőző kulcsszavak magyarázzák. Például egy téglalap létrehozására szolgáló kifejezést C++ vagy Java-szerű szintaxissal a következőképpen lehet leírni:

new Rectangle(100, 200);

Nem világos, hogy melyik argumentum melyik. Ezzel szemben Smalltalkban ez a kód a következőképpen lenne leírva:

Rectangle width: 100 height: 200

A címzett ebben az esetben a "Rectangle", egy osztály, és a válasz az osztály egy új példánya lesz a megadott szélességgel és magassággal. Végül, a legtöbb speciális (nem alfabetikus) karakter használható úgynevezett bináris üzenetként. Ezek lehetővé teszik a matematikai és logikai operátorok hagyományos formában történő leírását:

3 + 4

amely a "+" üzenetet küldi a 3-as címzettnek, 4-es argumentummal (amelynek válasza 7 lesz). Hasonlóképpen,

3 > 4

a 3-nak küldött ">" üzenet a 4. argumentummal (amelynek válasza hamis lesz).

Vegyük észre, hogy maga a Smalltalk-80 nyelv nem írja elő az operátorok jelentését. A fentiek kimenetelét csak az határozza meg, hogy az üzenet címzettje (jelen esetben egy Number példány) hogyan reagál a "+" és ">" üzenetekre.

Ennek a mechanizmusnak mellékhatása az operátorok túlterhelése. A ">" üzenet más objektumok számára is értelmezhető, lehetővé téve az "a > b" típusú kifejezések használatát az összehasonlításukhoz.

Kifejezések szerkesztés

Egy kifejezés több üzenetküldést is tartalmazhat. Ebben az esetben a kifejezések elemzése egyszerű fontossági sorrend szerint történik. Az unáris üzeneteknek van a legmagasabb prioritása, ezt követik a bináris üzenetek, majd a kulcsszavas üzenetek. Például:

3 factorial + 4 factorial between: 10 and: 100

a következőképpen értékelődik:

  1. 3 megkapja a "faktoriális" üzenetet és válaszol 6
  2. 4 megkapja a "factorial" üzenetet és 24-et válaszol.
  3. 6 megkapja a "+" üzenetet 24 argumentummal, és 30-at válaszol.
  4. 30 megkapja a "between:and:" üzenetet 10 és 100 argumentummal, és true választ ad.

Az utolsó elküldött üzenet válasza a teljes kifejezés eredménye.

A zárójelek szükség esetén megváltoztathatják az értékelés sorrendjét. Például,

(3 factorial + 4) factorial between: 10 and: 100

megváltoztatja a jelentést, így a kifejezés először a "3 faktoriális + 4" értéket számítja ki, ami 10-et eredményez. Ezután a 10 megkapja a második "faktoriális" üzenetet, ami 3628800-at eredményez. A 3628800 ezután megkapja a "between:and:" választ, ami hamis választ ad. Vegyük figyelembe, hogy mivel a bináris üzenetek jelentése nincs rögzítve a Smalltalk-80 szintaxisában, mindegyikük azonos prioritásúnak tekintendő, és egyszerűen balról jobbra haladva kerül kiértékelésre. Emiatt a bináris üzeneteket használó Smalltalk-kifejezések jelentése eltérhet a "hagyományos" értelmezésüktől:

3 + 4 * 5

kiértékelése "(3 + 4) * 5", ami 35-öt eredményez. Ahhoz, hogy a várt 23-as választ kapjuk, zárójeleket kell használni a műveletek sorrendjének egyértelmű meghatározására:

3 + (4 * 5)

Az egyoperandusú üzeneteket úgy lehet láncolni, hogy egymás után írjuk őket:

3 factorial factorial log

amely a "factorial"-t a 3-ra, majd a "factorial"-t az eredményre (6), majd a "log"-t az eredményre (720) küldi, így kapjuk a 2.85733 eredményt. A következő (feltételezett) példában szereplő kifejezések sorozata írható le, minden egyes kifejezést egy-egy ponttal elválasztva. Ez a példa először létrehozza az Ablak osztály egy új példányát, tárolja egy változóban, majd két üzenetet küld neki.

 | window |
  window := Window new.
  window label: 'Hello'.
  window open

Ha egy sor üzenetet küldünk ugyanannak a címzettnek, mint a fenti példában, akkor azokat kaszkádként is leírhatjuk, az egyes üzeneteket pontosvesszővel elválasztva:

  Window new
    label: 'Hello';
    open

A korábbi példa egyetlen kifejezésként való átírásával elkerülhető, hogy az új ablakot egy ideiglenes változóban tároljuk. A szokásos elsőbbségi szabályok szerint először az "new" unáris üzenetet küldjük el, majd a "label:" és a "open" üzeneteket az "new" válaszára. Egy kódblokk (egy névtelen függvény) kifejezhető egy literális értékként (ami egy objektum, mivel minden érték objektum). Ezt szögletes zárójelekkel érhetjük el:

[ :params | <message-expressions> ]

Ahol :params a kód által felvehető paraméterek listája. Ez azt jelenti, hogy a Smalltalk kód:

[:x | x + 1]

a következőképpen értelmezhető:

  :  

vagy lambda kifejezéssel kifejezve a következőképpen:

  :  

és

[:x | x + 1] value: 3

kiértékelhető a következőképpen

 

Vagy lambda kifejezéssel:

 

Az eredményül kapott blokkobjektum lezárást alkothat: bármikor hozzáférhet az őt körülvevő lexikai hatókörök változóihoz. A blokkok első osztályú objektumok.

A blokkok a value üzenet elküldésével hajthatók végre (léteznek összetett változatok is, hogy a blokknak paramétereket lehessen megadni, pl. 'value:value:' és 'valueWithArguments:').

A blokkok szó szerinti ábrázolása olyan újítás volt, amely egyrészt lehetővé tette, hogy bizonyos kódok lényegesen olvashatóbbak legyenek; az iterációt tartalmazó algoritmusokat világos és tömör módon lehetett kódolni. A Smalltalkban a blokkok segítségével tömören, néha egyetlen sorban is meg lehet írni olyan kódot, amelyet néhány nyelvben jellemzően ciklusokkal írnánk. De ami ennél is fontosabb, a blokkok lehetővé teszik a vezérlési struktúra üzenet és polimorfizmus használatával történő kifejezését, mivel a blokkok elhalasztják a számítást, a polimorfizmus pedig használható alternatívák kiválasztására. Tehát az if-then-else a Smalltalkban a következő módon írható és valósítható meg

expr ifTrue: [statements to evaluate if expr] ifFalse: [statements to evaluate if not expr]

Igaz metódusok a kiértékeléshez  

ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock
    ^trueAlternativeBlock value

Hamis metódusok a kiértékeléshez

 

ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock
    ^falseAlternativeBlock value
positiveAmounts := allAmounts select: [:anAmount | anAmount isPositive]

Megjegyzendő, hogy ez a funkcionális programozáshoz kapcsolódik, ahol a számítási mintákat (itt a kiválasztást) magasabb rendű függvényekké absztraháljuk. Például a select: üzenet egy gyűjteményen (Collection) egyenértékű a filter magasabb rendű függvénnyel egy megfelelő funkción (functor).

Ellenőrző struktúrák szerkesztés

A Smalltalkban a vezérlési struktúráknak nincs speciális szintaxisa. Ehelyett az objektumoknak küldött üzenetek formájában valósulnak meg. Például a feltételes végrehajtás úgy valósul meg, hogy az ifTrue: üzenetet elküldjük egy Boolean objektumnak, átadva argumentumként a kódblokkot, amely akkor és csak akkor hajtódik végre, ha a Boolean vevő igaz. A Boolean két alosztálya mindkettő implementálja az ifTrue:-t, ahol a True alosztályban lévő implementáció mindig kiértékeli a blokkot, a False alosztályban lévő implementáció pedig soha nem értékeli ki a blokkot.

A következő kód ezt szemlélteti:

result := a > b
    ifTrue:[ 'greater' ]
    ifFalse:[ 'less or equal' ]

A blokkok a felhasználó által definiált vezérlési struktúrák, felsorolók, látogatók, kivételkezelés, csatlakoztatható viselkedés és sok más minta megvalósítására is szolgálnak. Például:

| aString vowels |
aString := 'This is a string'.
vowels := aString select: [:aCharacter | aCharacter isVowel].

Az utolsó sorban a string a select: üzenetet küldi el egy olyan argumentummal, amely egy kódblokk literál. A kódkocka literálját egy predikátumfüggvényként használjuk, amelynek akkor és csak akkor kell igaz választ adnia, ha a karakterlánc egy elemét fel kell venni a "select:" üzenet argumentumaként szereplő kódkocka által képviselt tesztnek megfelelő karakterek gyűjteményébe. A String objektum úgy válaszol a "select:" üzenetre, hogy végigmegy a tagjain (elküldi magának a "do:" üzenetet), egyszer kiértékelve a kiválasztási blokkot ("aBlock") minden egyes karakterrel, amelyet argumentumként tartalmaz. Kiértékeléskor (a "value: each" üzenet elküldésével) a kiválasztási blokk (amelyre az "aBlock" paraméter hivatkozik, és amelyet a "[:aCharacter | aCharacter isVowel]" blokk literál definiál) egy bóluszi értékkel válaszol, amelyet a "ifTrue:" üzenet küld. Ha a boolean a true objektum, akkor a karakter hozzáadódik egy visszaadandó karakterlánchoz. Mivel a "select:" metódus a Collection absztrakt osztályban van definiálva, így is használható:

| rectangles aPoint collisions |
rectangles := OrderedCollection
  with: (Rectangle left: 0 right: 10 top: 100 bottom: 200)
  with: (Rectangle left: 10 right: 10 top: 110 bottom: 210).
aPoint := Point x: 20 y: 20.
collisions := rectangles select: [:aRect | aRect containsPoint: aPoint].

A kivételkezelési mechanizmus blokkokat használ kezelőként (hasonlóan a CLOS-stílusú kivételkezeléshez):

[
  some operation
] on:Error do:[:ex |
  handler-code
  ex return
]

A kivételkezelő "ex" argumentuma hozzáférést biztosít a felfüggesztett művelet állapotához (stack frame, sorszám, címzett és argumentumok stb.), és arra is szolgál, hogy szabályozza a számítás folytatását (az "ex proceed", "ex reject", "ex restart" vagy "ex return" valamelyikének elküldésével).

Osztályok szerkesztés

Ez egy osztály meghatározása:

Object subclass: #MessagePublisher
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''
    category: 'Smalltalk Examples'

Gyakran előfordul, hogy e meghatározás nagy részét a környezet tölti ki. Vegyük észre, hogy ez egy üzenet az Object osztály számára, hogy hozzon létre egy MessagePublisher nevű alosztályt. Más szóval: az osztályok első osztályú objektumok a Smalltalkban, amelyek ugyanúgy fogadhatnak üzeneteket, mint bármely más objektum, és dinamikusan létrehozhatók a végrehajtás idején.

Metódusok szerkesztés

Amikor egy objektum üzenetet kap, az üzenet nevének megfelelő metódus meghívásra kerül. A következő kód egy publish metódust definiál, és így meghatározza, hogy mi fog történni, amikor ez az objektum megkapja a 'publish' üzenetet.

publish
    Transcript show: 'Hello World!'

A következő módszer több argumentum fogadását és egy érték visszaadását mutatja be:

quadMultiply: i1 and: i2
    "This method multiplies the given numbers by each other and the result by 4."
    | mul |
    mul := i1 * i2.
    ^mul * 4

A módszer neve #quadMultiply:and:. A visszatérési értéket a ^ operátorral adjuk meg.

Vegyük észre, hogy az objektumok felelősek azért, hogy futásidőben dinamikusan meghatározzák, hogy melyik metódust kell végrehajtani egy üzenetre válaszul – míg sok nyelvben ez statikusan (néha vagy akár mindig) a fordításkor kerül meghatározásra.

Osztályok példányosítása szerkesztés

A következő kód:

MessagePublisher new

létrehozza (és visszaadja) a MessagePublisher osztály egy új példányát. Ezt jellemzően egy változóhoz rendeljük:

publisher := MessagePublisher new

Lehetőség van azonban arra is, hogy üzenetet küldjünk egy ideiglenes, névtelen objektumnak:

MessagePublisher new publish

Hello World példa szerkesztés

A Hello world programot gyakorlatilag minden új programozási nyelveket oktató szöveg használja az első megtanulandó programként, hogy bemutassa a nyelv legalapvetőbb szintaxisát és környezetét. A Smalltalk esetében a program megírása rendkívül egyszerű. A következő kód, a "show:" üzenetet a "Transcript" objektumnak küldjük el, amelynek argumentuma a String literális 'Hello, world!'. A "show:" metódus meghívása hatására az argumentumának (a String literál 'Hello, world!') karakterei megjelennek a transcript ("terminál") ablakában.

Transcript show: 'Hello, world!'.

Vegye figyelembe, hogy egy Transcript ablaknak nyitva kell lennie ahhoz, hogy láthassa a példa eredményeit.

Képalapú perzisztencia szerkesztés

A legtöbb népszerű programozási rendszer elválasztja a statikus programkódot (osztálydefiníciók, függvények vagy eljárások formájában) a dinamikus vagy futásidejű programállapottól (például objektumok vagy a programadatok más formáitól). Ezek a programkódot a program indításakor töltik be, és minden korábbi programállapotot kifejezetten konfigurációs fájlokból vagy más adatforrásokból kell újra létrehozni. Minden olyan beállítást, amelyet a program (és a programozó) nem ment el explicit módon, minden egyes újraindításkor újra kell állítani. Egy hagyományos program sok hasznos dokumentuminformációt is elveszít minden egyes alkalommal, amikor a program elment egy fájlt, kilép és újratölt. Ilyenkor olyan részletek vesznek el, mint a visszavonási előzmények vagy a kurzor pozíciója. A képalapú rendszerek nem kényszerítik ki mindezek elvesztését csak azért, mert a számítógépet kikapcsolják, vagy az operációs rendszert frissítik.

Sok Smalltalk rendszer azonban nem tesz különbséget a programadatok (objektumok) és a kód (osztályok) között. Valójában az osztályok objektumok. Így a legtöbb Smalltalk rendszer a teljes programállapotot (beleértve az osztály és nem osztály objektumokat is) egy képfájlban tárolja. A képet aztán a Smalltalk virtuális gép betöltheti, hogy egy Smalltalk-szerű rendszert visszaállítson egy korábbi állapotba. Ezt az Alan Kay által létrehozott és a diplomamunkájában leírt FLEX nyelv ihlette.

A Smalltalk-képek hasonlóak a (újraindítható) core dumps-hoz, és ugyanazt a funkcionalitást biztosíthatják, mint a core dumps, például késleltetett vagy távoli hibakeresést, teljes hozzáféréssel a program állapotához a hiba idején. Más nyelvek, amelyek az alkalmazáskódot egyfajta adatként modellezik, mint például a Lisp, gyakran használnak képalapú perzisztenciát is. Ez a perzisztencia-módszer a gyors fejlesztés szempontjából erőteljes, mivel az összes fejlesztési információ (pl. a program elemzési fái) elmentésre kerül, ami megkönnyíti a hibakeresést. Azonban komoly hátrányai is vannak, mint valódi perzisztencia mechanizmusnak. Egyrészt a fejlesztők gyakran el akarják rejteni az implementációs részleteket, és nem teszik azokat elérhetővé a futásidejű környezetben. Törvényességi és karbantartási okokból, ha bárki számára lehetővé tesszük, hogy futásidőben módosítsa a programot, az elkerülhetetlenül olyan komplexitást és potenciális hibákat eredményez, amelyek nem lennének lehetségesek egy olyan lefordított rendszerrel, amely nem teszi közzé a forráskódot a futásidejű környezetben. Továbbá, bár a perzisztencia mechanizmus könnyen használható, nem rendelkezik a legtöbb többfelhasználós rendszerhez szükséges valódi perzisztencia képességekkel. A legnyilvánvalóbb az a képesség, hogy tranzakciókat hajtsunk végre több, ugyanazt az adatbázist párhuzamosan elérő felhasználóval.

A hozzáférés szintje szerkesztés

A Smalltalk-80-ban minden módosítható egy futó programból. Ez azt jelenti, hogy például az IDE megváltoztatható egy futó rendszerben anélkül, hogy azt újra kellene indítani. Egyes megvalósításokban a nyelv szintaxisa vagy a szemétgyűjtés megvalósítása is menet közben módosítható. Még a true become: false utasítás is érvényes a Smalltalkban, bár végrehajtása nem ajánlott.

Just-in-time fordítás szerkesztés

 

A Smalltalk programokat általában bytecode-ba fordítják, amelyet aztán egy virtuális gép értelmez, vagy dinamikusan lefordít gépi kóddá.

A megvalósítások listája szerkesztés

OpenSmalltalk szerkesztés

Az OpenSmalltalk VM (OS VM), a Smalltalk Runtime runner egy figyelemre méltó implementációja, amelyen számos modern Smalltalk implementáció alapul, vagy amelyből származik. Maga az OS VM a Smalltalk forráskódfájlokból (a Smalltalk egy Slang nevű részhalmazát használva) natív C nyelvű forráskóddá transzpilálódik (a VMMaker nevű transzpiler segítségével), amely viszont a hardver adott platformja és architektúrája ellen fordítva gyakorlatilag lehetővé teszi a Smalltalk-képek platformok közötti futtatását. A forráskód elérhető a GitHubon, és MIT licenc alatt terjesztik. Az OS VM-en alapuló ismert Smalltalk implementációk a következők:

  • Squeak, az eredeti nyílt forráskódú Smalltalk, amelyre az OpenSmalltalk VM épült.
  • Pharo Smalltalk, egy nyílt forráskódú, keresztplatformos nyelv.
  • Cuis-Smalltalk, a Squeak nyílt forráskódú, kis méretű, tiszta és Smalltalk-80 kompatibilis forkja.[13]
  • Haver-Smalltalk a Cuis kiterjesztése egy teljes modulrendszerrel.
  • Croquet VM, egy Squeak-hez kapcsolódó Smalltalk VM a Croquet projekthez

Egyebek szerkesztés

  • Amber Smalltalk, runs on JavaScript via transpilation
  • Cincom has the following Smalltalk products: ObjectStudio, VisualWorks and WebVelocity.
  • Visual Smalltalk Enterprise, and family, including Smalltalk/V
  • Smalltalk/X, developed by Claus Gittinger
  • F-Script, macOS-only implementation written in 2009
  • GemTalk Systems, GemStone/S
  • GNU Smalltalk, headless (lacks GUI) implementation of the Smalltalk
  • StepTalk, GNUstep scripting framework uses Smalltalk language on an Objective-C runtime
  • VisualAge Smalltalk
  • Rosetta Smalltalk, developed by Scott Warren in 1979 and announced as a cartridge for the Exidy Sorcerer computer but never released 
  • VAST Platform (VA Smalltalk), developed by Instantiations, Inc
  • Little Smalltalk
  • Object Arts, Dolphin Smalltalk
  • Object Connect, Smalltalk MT Smalltalk for Windows
  • Pocket Smalltalk, runs on Palm Pilot

Jegyzetek szerkesztés

  1. ANSI Smalltalk Standard. Smalltalk.org, 2004 [2006. február 16-i dátummal az eredetiből archiválva]. (Hozzáférés: 2021. március 2.)
  2. Stack Overflow Developer Survey 2018
  3. Kay, Alan: The Early History of Smalltalk. (Hozzáférés: 2007. szeptember 13.)
  4. Krasner (August–September 1988). „A Cookbook for Using the Model-View-Controller User Interface Paradigm in Smalltalk -80”. Journal of Object-Oriented Programming.  
  5. Our Influence. cincomsmalltalk.com. (Hozzáférés: 2013. december 16.)
  6. Kay: Prototypes vs Classes (e-mail on Squeak list), 1998. október 10.
  7. Goldberg, Adele. Smalltalk-80 The Language. Addison Wesley, 31, 75–89. o. (1989). ISBN 0-201-13688-0 
  8. Clark (1997). „Metaclasses and Reflection in Smalltalk”.  
  9. Ducasse: Seaside – A Multiple Control Flow Web Application Framework. scg.unibe.ch. Software Composition Group Institut fur Informatik und angewandte Mathematik Universitaat Bern, Switzerland. (Hozzáférés: 2013. december 16.)
  10. Foote (1–6 October 1989). „Reflective Facilities in Smalltalk-80”. Oopsla '89, 327–335. o. DOI:10.1145/74877.74911. (Hozzáférés: 2013. december 16.)  
  11. Smith (1982. január 1.). „Procedural Reflection in Programming Languages”. MIT Technical Report (MIT-LCS-TR-272). (Hozzáférés: 2013. december 16.)  
  12. Archivált másolat. [2018. június 13-i dátummal az eredetiből archiválva]. (Hozzáférés: 2021. december 17.)
  13. Table of Contents, Cuis Smalltalk

 

Fordítás szerkesztés

Ez a szócikk részben vagy egészben a Smalltalk című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.

További információk szerkesztés