Simge (programlama dili) - Icon (programming language)

Simge
Simge logosu.png
paradigma çoklu paradigma : yapılandırılmış , metin yönelimli
Tarafından tasarlandı Ralph Griswold
İlk ortaya çıktı 1977 ; 44 yıl önce ( 1977 )
kararlı sürüm
9.5.20 / 13 Ağustos 2020 ; 13 ay önce ( 2020-08-13 )
Yazma disiplini dinamik
İnternet sitesi www .cs .arizona .edu /icon
Başlıca uygulamalar
Simge, Jcon
lehçeler
tek simge
Tarafından etkilenmiş
SNOBOL , SL5, ALGOL
Etkilenen
Unicon, Python , Goaldi

Icon , kodun geçerli değerlerle birlikte bir "başarı" veya döndürülecek geçerli bir veri olmadığını belirten bir "başarısızlık" döndürdüğü "hedefe yönelik yürütme" kavramına dayanan çok üst düzey bir programlama dilidir . Belirli bir kod bloğunun başarısı ve başarısızlığı, daha sonraki işlemleri yönlendirmek için kullanılırken, geleneksel diller , aynı amaçlara ulaşmak için tipik olarak programcı tarafından yazılan boole mantığını kullanır . Temel kontrol yapılarının mantığı genellikle Icon'da örtük olduğundan, genel görevler daha az açık kodla tamamlanabilir.

Simge, Ralph Griswold tarafından , SNOBOL diline önemli bir katkıda bulunduğu Bell Labs'ten ayrıldıktan sonra tasarlandı . SNOBOL, 1970'lerin başlarındaki standartlara göre tarihli sözdizimi olarak kabul edilecek olan bir dizi işleme diliydi. Arizona Üniversitesi'ne taşındıktan sonra , SL5'in altında yatan SNOBOL kavramlarını daha da geliştirdi, ancak sonucun bir başarısızlık olduğunu düşündü. Bu, daha tanıdık sözdizimi ile Snobol benzeri dillerin kısa ama kavramsal olarak yoğun bir kod harmanlayarak anlamlı güncellenen Simge yol açtı ALGOL gibi dilleri -inspired C veya Pascal .

Ona ilham veren diller gibi, Icon'un birincil kullanım alanı, dizeleri ve metinsel kalıpları yönetmektir . Dize işlemleri genellikle başarısız olur, örneğin, "dünya" içinde "the" bulmak. Çoğu dilde bu, geçerli olmayan bir sonuç kullanmaktan kaçınmak için test etmeyi ve dallandırmayı gerektirir. Icon'da bu tür testlerin çoğu gerekli değildir ve programcı tarafından yazılan kod miktarını azaltır. Karmaşık kalıp işleme, Perl gibi daha özel dillere benzer, ancak diğer ALGOL benzeri dillerin kullanıcılarına aşina olan daha işlev odaklı bir sözdizimini koruyarak , birkaç kısa kısa kod satırında gerçekleştirilebilir .

Simge nesne yönelimli değildir , ancak 1996'da Idol adlı nesne yönelimli bir uzantı geliştirildi ve sonunda Unicon oldu . Aynı zamanda, özellikle etkili olan basit jeneratörleri ile diğer dillere de ilham verdi; Icon'un oluşturucuları, Python programlama dili için büyük bir ilham kaynağıydı .

Tarih

SNOBOL

Geriye dönük olarak SNOBOL1 olarak bilinen orijinal SNOBOL çabası, 1962 sonbaharında Bell Labs Programlama Araştırma Çalışmaları Departmanında başlatıldı . Bu çaba, polinom formül manipülasyonu, sembolik entegrasyon ve Markov zincirlerini incelemek için SCL dilini kullanmaya çalışmanın hayal kırıklıklarına bir tepkiydi . Bölüm başkanı Chester Lee tarafından yazılan SCL, hem yavaştı hem de basit projeler için bile çok sayıda kodla sonuçlanan düşük seviyeli bir sözdizimine sahipti. Altı kişilik bölümün tüm üyeleri Ivan Polonsky, Ralph Griswold ve David Farber, COMIT dilini kısaca düşündükten sonra, bu sorunları çözmek için kendi dillerini yazmaya karar verdiler.

İlk sürümler, 1963'ün başlarında IBM 7090'da çalışıyordu ve yaz aylarında inşa edilmiş ve Bell genelinde kullanılıyordu. Bu, neredeyse anında, bir dizi yerleşik işlev ve harici montaj dili koduna bağlanma yeteneği ekleyen SNOBOL2'ye yol açtı . Nisan 1964'te piyasaya sürüldü ve çoğunlukla Bell'de kullanıldı, ancak Project MAC'de de bir miktar kullanım gördü . Sistem işlevlerinin tanıtılması, çoğunlukla Temmuz 1964'te piyasaya sürülen SNOBOL3'ün ana özelliği olan kullanıcı işlevlerine duyulan ihtiyacı göstermeye hizmet etti.

SNOBOL3'ün tanıtımı , SNOBOL'un yeniden yazılmasını gerektirecek yeni GE 645 anabilgisayarının eklenmesi de dahil olmak üzere Bell Labs bilgi işlem bölümündeki büyük değişikliklere karşılık geldi. Bunun yerine ekip, sanal bir makinede çalışacak, SNOBOL Intermediate Language için SIL adlı ve yeterince güçlü herhangi bir platforma kolayca taşınmasını sağlayan yeni bir sürüm yazmayı önerdi . Bu öneri Eylül 1965'te SNOBOL4 olarak kabul edildi. Bu zamana kadar, Ağustos 1966'da dilin önemli ölçüde geliştirilmiş bir versiyonu için planlar ortaya çıktı. 1960'ların geri kalanında dil üzerinde daha fazla çalışma devam etti, özellikle daha sonraki versiyonda ilişkisel dizi tipini ekledi. tablo olarak adlandırdıkları .

SL5, Simge'ye yönlendiriyor

Griswold , Ağustos 1971'de Arizona Üniversitesi'nde profesör olmak için Bell Laboratuarlarından ayrıldı . O sırada SNOBOL4'ü bir araştırma aracı olarak tanıttı.

Başlangıçta 1960'ların başında geliştirilen bir dil olan SNOBOL'un sözdizimi, FORTRAN ve COBOL gibi diğer erken programlama dillerinin işaretlerini taşır . Bu dillerin çoğu sütun düzeninin doğal olduğu delikli kartlara girildiği için özellikle dil sütuna bağlıdır . Ek olarak, kontrol yapıları , ALGOL 60'ın piyasaya sürülmesinden sonra olmazsa olmaz bir özellik haline gelen blokların kullanımından ziyade neredeyse tamamen kod etrafında dallanmaya dayanıyordu . Arizona'ya taşındığında, SNOBOL4'ün sözdizimi umutsuzca modası geçmişti.

Griswold, SNOBOL'un altında yatan başarı/başarısızlık konseptini if/then gibi geleneksel akış kontrol yapılarıyla uygulama çabalarına başladı. Bu, "SNOBOL Language 5"in kısaltması olan SL5 oldu, ancak sonuç tatmin edici değildi. 1977'de yeni bir versiyonu düşünmek için dile döndü. SL5'te tanıtılan çok güçlü fonksiyon sistemini daha basit bir askıya alma/devam etme konseptiyle terk etti ve aşağıdaki ilkelerle SNOBOL4'ün doğal halefi için yeni bir konsept geliştirdi;

  • SNOBOL4'ün felsefi ve sematik temeli
  • SL5 sözdizimsel temeli
  • Genelleştirilmiş prosedür mekanizması hariç SL5 özellikleri

Yeni dil başlangıçta SNOBOL5 olarak biliniyordu, ancak temeldeki konsept dışında SNOBOL'dan önemli ölçüde farklı olduğu için nihayetinde yeni bir isim istendi. "s" yi "C"ye bir tür saygı olarak gördükten sonra, ancak bu ismin kullanıldığı dizgi belgelerindeki problemler nedeniyle sonuçta terk edildi. Bir dizi yeni isim önerildi ve terk edildi; Irving, bard ve "Dil" için "TL". Bu sırada Xerox PARC , grafik kullanıcı arayüzleri üzerindeki çalışmalarını yayınlamaya başladı ve "simge" terimi bilgisayar sözlüğüne girmeye başladı. Sonunda "Simge" seçilmeden önce adı "ikon" olarak değiştirmeye karar verildi.

Dilim

Temel sözdizimi

Icon dili, yapılandırılmış programlama dillerinin ALGOL sınıfından türetilmiştir ve bu nedenle C veya Pascal'a benzer sözdizimine sahiptir . Simge, atamalar için sözdizimi, anahtar sözcük ve benzer sözdizimi kullanan Pascal'a en çok benzer . Öte yandan Icon, yürütme gruplarını yapılandırmak için C stili ayraçlar kullanır ve programlar, adlı bir prosedürü çalıştırarak başlar . :=proceduremain

Birçok yönden Icon, çoğu komut dosyası diliyle (ayrıca alındıkları SNOBOL ve SL5'in yanı sıra) özellikleri paylaşır : değişkenlerin bildirilmesi gerekmez, türler otomatik olarak yayınlanır ve sayılar dizelere dönüştürülebilir ve otomatik olarak geri döndürülebilir. Hepsinde olmasa da pek çok betik dilinde ortak olan bir başka özellik de satır sonu karakterinin olmamasıdır; Simge'de noktalı virgülle bitmeyen satırlar, mantıklıysa ima edilen noktalı virgülle biter.

Prosedürler, Icon programlarının temel yapı taşlarıdır. Pascal adlandırma kullanmalarına rağmen, daha çok C işlevleri gibi çalışırlar ve değer döndürebilirler; Icon'da functionanahtar kelime yok .

 procedure doSomething(aString)
   write(aString)
 end

Hedefe yönelik yürütme

SNOBOL'deki anahtar kavramlardan biri, işlevlerinin sihirli sayılar veya diğer teknikleri kullanmak yerine, dilin ilkelleri olarak "başarı" veya "başarısızlık" döndürmesiydi . Örneğin, bir alt dizenin başka bir dize içindeki konumunu döndüren bir işlev, çoğu dil çalıştırma zamanı sisteminde bulunan yaygın bir rutindir ; örneğin, JavaScript'te , "Merhaba, Dünya!" içindeki "Dünya" kelimesinin konumunu bulmak isteyebilir, bu da ile tamamlanır ve 7 döndürür. Bunun yerine kod istenirse "başarısız" olur, arama terimi dizede görünmediğinden. JavaScript'te, çoğu dilde olduğu gibi, bu, bu durumda -1 gibi bir sihirli sayı döndürülerek belirtilir. position = "Hello, World".indexOf("World")position = "Hello, World".indexOf("Goodbye")

SNOBOL'de bu türden bir hata, özel bir değer döndürür, fail. SNOBOL'un sözdizimi, işlemin başarısı veya başarısızlığı üzerinde doğrudan çalışır, ayrı bir test yazmak zorunda kalmadan kodun etiketli bölümlerine atlar. Örneğin, aşağıdaki kod "Merhaba dünya!" Beş kere:

* SNOBOL program to print Hello World
      I = 1
LOOP  OUTPUT = "Hello, world!"
      I = I + 1
      LE(I, 5) : S(LOOP)
END

Döngüyü gerçekleştirmek için LE, indeks değişkeni I üzerinde, eşittir veya küçüktür operatörü çağrılır ve eğer Sbaşarılı olursa, yani I 5'ten küçüktür, adlandırılmış etikete dallanır LOOPve devam eder.

Icon, başarı veya başarısızlığa dayalı temel akış kontrolü kavramını korudu, ancak dili daha da geliştirdi. Değişikliklerden biri, 1960'ların sonlarında bilgisayar endüstrisini kasıp kavuran yapılandırılmış programlama stiline GOTOuygun olarak etiketli dallanmanın blok odaklı yapılarla değiştirilmesiydi . İkincisi, tüm blokların bir bütün olarak başarılı veya başarısız olması için çağrı zinciri boyunca "başarısızlığın" geçirilmesine izin vermekti. Bu, Simge dilinin anahtar kavramıdır. Geleneksel dillerde, boole mantığına dayalı başarıyı veya başarısızlığı test etmek için kod eklemek ve ardından sonuca göre dallandırmak gerekirken, bu tür testler ve dallar Simge koduna özgüdür ve açıkça yazılması gerekmez.

Örneğin, Java programlama dilinde yazılmış bu kod parçasını düşünün . read()Bir (önceden açılmış) dosyadan bir karakter okumak için işlevi çağırır, sonucu değişkene atar ave ardından writedeğerini abaşka bir dosyaya atar . Sonuç, bir dosyayı diğerine kopyalamaktır. readsonunda dosyadan okunacak karakter bitecek, potansiyel olarak ilk çağrısında, bu da abelirsiz bir durumda bırakacak ve potansiyel olarak boş gösterici istisnasına neden writeolacaktır . Bunu önlemek için, bu durumda özel değeri (dosya sonu) döndürür, bu da bunu önlemek için açık bir test gerektirir : readEOFwrite

 while ((a = read()) != EOF) {
   write(a);
 }

Buna karşılık, Simge'de read()işlev, bir metin satırı veya döndürür &fail. dil tarafından bağlama bağlı olarak "işlemeyi durdur" veya "başarısız durumu yap" anlamına geldiği açıkça anlaşıldığından, &failbasit bir analog değildir EOF. Simgedeki eşdeğer kod:

 while a := read() then write(a)

Bu, "okuma başarısız olduğu sürece, yazma çağrısı yapın, aksi takdirde dur" anlamına gelir. Java örneğinde olduğu gibi sihirli sayıya karşı bir test belirtmeye gerek yoktur, bu örtüktür ve elde edilen kod basitleştirilmiştir. Başarı ve başarısızlık çağrı zincirinden geçtiği için, işlevleri diğerlerinin içine gömebilir ve iç içe işlev başarısız olduğunda dururlar . Örneğin, yukarıdaki kod şuna indirgenebilir:

 while write(read())

Bu sürümde, readbaşarısız olursa, writebaşarısız olur ve whiledurur. Icon'un dallanma ve döngü yapılarının tümü, programcı tarafından sağlanan rastgele bir boole testine değil, içlerindeki kodun başarısına veya başarısızlığına bağlıdır. "testi" bir değer döndürürse bloğu ifgerçekleştirir ve thendöndürürse elseblok veya sonraki satıra geçer &fail. Aynı şekilde, whilebir fail alana kadar bloğunu çağırmaya devam eder. Simge, bu kavramı hedefe yönelik yürütme olarak ifade eder .

Başarı ve başarısızlık kavramını istisna kavramıyla karşılaştırmak önemlidir ; istisnalar olağandışı durumlardır, beklenen sonuçlar değildir. Simgedeki başarısızlıklar beklenen sonuçlardır; bir dosyanın sonuna ulaşmak bir istisna değil, beklenen bir durumdur. İkon, istisna benzeri durumlarda sıklıkla kullanılsa da, geleneksel anlamda istisna işlemeye sahip değildir. Örneğin, okunan dosya mevcut değilse, readözel bir durum belirtilmeden başarısız olur. Geleneksel dilde, bu "diğer koşulların" hiçbir doğal belirtilme biçimi yoktur; ek sihirli sayılar kullanılabilir, ancak daha tipik olarak istisna işleme, bir değeri "atmak" için kullanılır. Örneğin, Java kodundaki eksik bir dosyayı işlemek için şunları görebiliriz:

 try {
   while ((a = read()) != EOF) {
     write(a);
   }
 } catch (Exception e) {
   // something else went wrong, use this catch to exit the loop
 }

Bu durum iki karşılaştırmaya ihtiyaç duyar: biri EOF için, diğeri tüm diğer hatalar için. Java, Simge altında olduğu gibi, istisnaların mantık öğeleri olarak karşılaştırılmasına izin vermediğinden, try/catchbunun yerine uzun sözdizimi kullanılmalıdır. Try blokları ayrıca, herhangi bir istisna atılmasa bile bir performans cezası uygular; bu, Icon'un normalde kaçındığı dağıtılmış bir maliyettir .

Icon, geleneksel boole testlerini gerçekleştirmek için aynı amaca yönelik mekanizmayı kullanır, ancak küçük farklılıklar vardır. Gibi basit bir karşılaştırma , çoğu dilde olduğu gibi "sağdaki işlemler doğru olarak değerlendirilirse" anlamına gelmez; bunun yerine, "sağdaki işlemler başarılı olursa" gibi bir anlama gelir . Bu durumda karşılaştırma doğruysa < operatörü başarılı olur. İfade başarılı olursa yan tümcesini, başarısız olursa veya sonraki satırı çağırır . sonuç, diğer dillerde görülen geleneksel if/then ile benzerdir, if is less öğesini gerçekleştirir.İncelik , aynı karşılaştırma ifadesinin herhangi bir yere yerleştirilebilmesidir, örneğin: if a < b then write("a is smaller than b")ifthenelseifthenab

 write(a < b)

Diğer bir fark, <operatörün başarılı olursa ikinci argümanını döndürmesidir, bu örnekte, değerinden bbüyükse yazılma değeri ile sonuçlanacaktır a, aksi takdirde hiçbir şey yazılmaz. Bu başlı başına bir test değil , bir değer döndüren bir operatör if a < b < colduğundan, çoğu dilde iki eşitsizliğin birleşimi olarak yazılması gereken ortak bir karşılaştırma türü gibi şeylere izin vererek bir araya dizilebilirler if (a < b) && (b < c).

Hedefe yönelik yürütmenin önemli bir yönü, bir prosedür başarısız olursa, programın önceki bir duruma geri sarmak zorunda kalabilmesidir, bu görev geri izleme olarak bilinir . Örneğin, bir başlangıç ​​konumuna bir değişken ayarlayan ve ardından değeri değiştirebilecek işlemler gerçekleştiren kodu düşünün - bu, örneğin, imleci tararken dize boyunca ilerletecek olan dize tarama işlemlerinde yaygındır. Prosedür başarısız olursa, bu değişkenin sonraki okumalarının, dahili olarak manipüle edildiği durumu değil, orijinal durumu döndürmesi önemlidir. Bu görev için Icon, tersine çevrilebilir atama operatörüne <-ve tersine çevrilebilir değiş tokuşa , sahiptir <->. Örneğin, daha büyük bir dize içinde bir kalıp dizesi bulmaya çalışan bir kod düşünün:

 {
   (i := 10) &
   (j := (i < find(pattern, inString)))
 }

Bu kod i, aramanın başlangıç ​​konumu olan 10'a taşınarak başlar . Ancak, findbaşarısız olursa, blok bir bütün olarak başarısız olur, bu ida istenmeyen bir yan etki olarak 10'da bırakılan değerle sonuçlanır . Değiştirme i := 10ile i <- 10gösterir iblok başarısız olursa önceki değerine sıfırlanır olmalıdır. Bu , yürütmede bir atomsallık analogu sağlar .

jeneratörler

Simge'deki ifadeler tek bir değer döndürebilir, örneğin, x < 5x'in değeri 5'ten küçükse veya başarısız olursa, x'i değerlendirir ve döndürür. Bununla birlikte Icon, başarıyı veya başarısızlığı hemen döndürmeyen ve bunun yerine her çağrıldıklarında yeni değerler döndüren prosedürler kavramını da içerir . Bunlar jeneratörler olarak bilinir ve Simge dilinin önemli bir parçasıdır. Simge dilinde, bir ifadenin veya işlevin değerlendirilmesi, bir sonuç dizisi üretir . Sonuç dizisi, ifade veya işlev tarafından üretilebilecek tüm olası değerleri içerir. Sonuç dizisi tükendiğinde, ifade veya işlev başarısız olur.

Simge herhangi prosedür kullanılarak kontrol tek veya birden çok değeri, geri dönmek için izin verir fail, returnve suspendanahtar kelimeler. Bu anahtar sözcüklerden herhangi birinin bulunmadığı bir yordam, &failyürütme işlemin bir yordamın başına geçtiğinde ortaya çıkan döndürür end. Örneğin:

 procedure f(x)
   if x > 0 then {
     return 1
   }
 end

Arama f(5)1 döndürür, ancak arama f(-1)geri döner &fail. Bu, örneğin, açık olmayan davranışlara yol açabilir, write(f(-1))çünkü fbaşarısız olur ve çalışmasını askıya alır write.

Bir prosedürü jeneratöre dönüştürmek suspend, "bu değeri döndür ve tekrar çağrıldığında bu noktada yürütmeye başla" anlamına gelen anahtar kelimeyi kullanır . Bu bakımdan static, C ve ' deki kavramın bir kombinasyonu gibi bir şeydir return. Örneğin:

 procedure ItoJ(i, j)
   while i <= j do {
     suspend i
     i +:= 1
   }
   fail
 end

ile başlayan ve a iile biten bir dizi sayı jdöndüren ve ardından bundan sonra dönen bir üreteç oluşturur &fail. suspend idurur ve değerini verir ikonumunun herhangi bir Sıfırlanmasını olmadan. Aynı işleve başka bir çağrı yapıldığında, yürütme o noktada önceki değerlerle başlar. Bu durumda, bu onun gerçekleştirmesine neden olur i +:= 1, while bloğunun başına geri döner ve ardından bir sonraki değeri döndürür ve yeniden askıya alır. Bu i <= j, başarısız olana kadar devam eder , bu noktada bloktan çıkar ve çağırır fail. Bu, yineleyicilerin kolaylıkla oluşturulmasını sağlar.

Başka bir tür jeneratör oluşturucu, boole operatörü gibi görünen ve çalışan alternatördüror . Örneğin:

 if y < (x | 5) then write("y=", y)

Bu, "y, x veya 5'ten küçükse..." der gibi görünür, ancak aslında, listenin sonundan düşene kadar değerleri döndüren bir üreteç için kısa bir biçimdir. Listenin değerleri işlemlere "enjekte edilir", bu durumda <. Bu örnekte, sistem önce y < x'i test eder, eğer x gerçekten y'den büyükse, x'in değerini döndürür, test başarılı olur ve y'nin değeri thenyan tümceye yazılır . Ancak x, y'den büyük değilse başarısız olur ve alternatör y < 5 yaparak devam eder. Bu test geçerse y yazılır. y, x veya 5'ten küçük değilse, alternatör testleri biter ve başarısız olur, ifbaşarısız olur ve writegerçekleştirilmez. Böylece, x veya 5'ten küçükse y değeri konsolda görünecek ve böylece bir boole amacını yerine getirecektir or. İşlevler, parametrelerinin değerlendirilmesi başarılı olmadıkça çağrılmayacaktır, bu nedenle bu örnek şu şekilde kısaltılabilir:

 write("y=", (x | 5) > y)

Dahili olarak, alternatör basit bir şey değildir orve aynı zamanda keyfi değer listeleri oluşturmak için de kullanılabilir. Bu, aşağıdaki gibi keyfi değerler üzerinde yineleme yapmak için kullanılabilir:

 every i := (1|3|4|5|10|11|23) do write(i)

Tamsayı listeleri birçok programlama bağlamında yaygın olarak bulunduğundan, Icon ayrıca geçici tamsayı üreteçleri tooluşturmak için anahtar kelimeyi içerir :

 every k := i to j do write(k)

kısaltılabilir:

 every write(1 to 10)

Simge kesin olarak yazılmamıştır, bu nedenle alternatör listeleri farklı türde öğeler içerebilir:

 every i := (1 | "hello" | x < 5)  do write(i)

Bu, x'in değerine bağlı olarak 1, "merhaba" ve belki 5 yazar.

Benzer şekilde bağlaç operatörü , &, boole andoperatörüne benzer bir şekilde kullanılır :

 every x := ItoJ(0,10) & x % 2 == 0 do write(x)

Bu kod çağırır ItoJve x'e atanan 0 başlangıç ​​değerini döndürür. Daha sonra bağlacın sağ tarafını gerçekleştirir ve x % 20'a eşit olduğu için değeri yazar. Daha sonra ItoJ, 1'den x'e atayan, sağ tarafta başarısız olan ve hiçbir şey yazdırmayan üreteci tekrar çağırır . Sonuç, 0'dan 10'a kadar her çift tam sayının bir listesidir.

Oluşturucu kavramı, dize işlemleriyle kullanıldığında özellikle kullanışlı ve güçlüdür ve Icon'un genel tasarımı için temel bir temel oluşturur. indexOfBirçok dilde bulunan işlemi düşünün ; bu işlev, bir dizeyi diğerinin içinde arar ve konumunun bir dizini veya bulunamazsa sihirli bir sayı döndürür. Örneğin:

 s = "All the world's a stage. And all the men and women merely players";
 i = indexOf("the", s);
 write(i);

Bu, dizeyi tarar, s"the"nin ilk oluşumunu bulur ve bu durumda 4 dizini döndürür. Bununla birlikte, dize, "the" dizesinin iki örneğini içerir, bu nedenle ikinci örneği döndürmek için alternatif bir sözdizimi olur. kullanılmış:

 j = indexOf("the", s, i+1);
 write(j);

Bu, konum 5'ten başlayarak tarama yapmasını söyler, bu nedenle daha önce bulduğumuz ilk örnekle eşleşmeyecektir. Ancak, "the"nin ikinci bir örneği olmayabilir -birincisi de olmayabilir- bu nedenle gelen dönüş değeri indexOfeşleşme olmadığını belirtmek için kullanılan sihirli sayı -1 ile kontrol edilmelidir. Her örneğin konumunu yazdıran eksiksiz bir rutin:

 s = "All the world's a stage. And all the men and women merely players";
 i = indexOf("the", s);
 while i != -1 {
   write(i);
   i =  indexOf("the", s, i+1);
 }

Icon'da eşdeğer findbir üreteçtir, bu nedenle aynı sonuçlar tek bir satırla oluşturulabilir:

 s := "All the world's a stage. And all the men and women merely players"
 every write(find("the", s))

Elbette, örneğin, ilk dört sütunda bir satır numarası, bir boşluk ve ardından bir metin satırı içeren bir metin dosyasını tararken, girdinin bir noktasından sonra bir dize bulmak istendiği zamanlar vardır. Satır numaralarını atlamak için hedefe yönelik yürütme kullanılabilir:

 every write(5 < find("the", s))

Konum, yalnızca 5. konumdan sonra "the" görünürse döndürülür; aksi takdirde karşılaştırma başarısız olur, başarısız olur ve yazma gerçekleşmez.

everyOperatör benzer whileher öğenin bir jeneratör tarafından döndürülen ve başarısızlık üzerine çıkarken, döngü:

  every k := i to j do
   write(someFunction(k))

everyve arasında önemli bir fark vardır while; whilebaşarısız olana kadar ilk sonucu yeniden değerlendirirken, everybir jeneratörden sonraki değeri alır. everyaslında Smalltalk altındaki bloklara benzer bir şekilde fonksiyona değerler enjekte eder . Örneğin, yukarıdaki döngü şu şekilde yeniden yazılabilir:

 every write(someFunction(i to j))

Bu durumda, i'den j'ye kadar olan değerler enjekte edilecek someFunctionve (potansiyel olarak) birden fazla çıktı satırı yazılacaktır.

Koleksiyonlar

Simge, yığınlar ve kuyruklar olarak da kullanılabilen listeler , tablolar (diğer dillerde haritalar veya sözlükler olarak da bilinir), kümeler ve diğerleri dahil olmak üzere çeşitli koleksiyon türleri içerir . Simge, bunlara yapılar olarak atıfta bulunur . Koleksiyonlar doğal oluşturuculardır ve patlama sözdizimi kullanılarak kolayca çağrılabilir. Örneğin:

 lines := []                    # create an empty list
 while line := read() do {      # loop reading lines from standard input
   push(lines, line)            # use stack-like syntax to push the line on the list
 }
 while line := pop(lines) do {  # loop while lines can be popped off the list
   write(line)                  # write the line out
 }

Daha önceki örneklerde görüldüğü gibi başarısızlık yayılımını kullanarak testleri ve döngüleri birleştirebiliriz:

 lines := []                    # create an empty list
 while push(lines, read())      # push until empty
 while write(pop(lines))        # write until empty

Liste koleksiyonu bir oluşturucu olduğundan, bu, patlama sözdizimi ile daha da basitleştirilebilir:

 lines := []
 every push(lines, !&input)
 every write(!lines)

Bu durumda, patlama, writeIcon'un diziden tek tek bir metin satırı döndürmesine ve sonunda başarısız olmasına neden olur. standart girdiden bir satır okuyan &inputüreteç tabanlı bir analogdur, readbu nedenle dosya bitene kadar satırları okumaya devam eder. !&input

Simge türsüz olduğundan, listeler herhangi bir farklı değer türünü içerebilir:

aCat := ["muffins", "tabby", 2002, 8]

Öğeler diğer yapıları içerebilir. Daha büyük listeler oluşturmak için Icon, oluşturucuyu içerir list; i := list(10, "word")"kelime"nin 10 kopyasını içeren bir liste oluşturur. Diğer dillerdeki diziler gibi, Simge de öğelerin konuma göre aranmasına izin verir, örn weight := aCat[4]. Diğer listelerin öğelerinden yeni listelerin oluşturulmasına izin veren dizi dilimleme dahil edilmiştir, örneğin, "tabby",2002aCat := Cats[2:4] içeren aCat adında yeni bir liste üretir .

Tablolar aslında tamsayılar yerine rastgele dizin anahtarlarına sahip listelerdir:

 symbols := table(0)
 symbols["there"] := 1
 symbols["here"] := 2

Bu kod, herhangi bir bilinmeyen anahtarın varsayılan değeri olarak sıfır kullanacak bir tablo oluşturur. Daha sonra "orada" ve "burada" tuşları ve 1 ve 2 değerleri ile tabloya iki öğe ekler.

Kümeler de listelere benzer, ancak verilen herhangi bir değerin yalnızca tek bir üyesini içerir. Simge, ++iki kümenin **birleşimini, kesişimi ve --farkı üretmeyi içerir . Simge, çeşitli karakterleri içeren bir dizi önceden tanımlanmış "Cset" içerir. Simge &ucase, &lcase, &letters, ve içinde dört standart Cset vardır &digits. Bir dizeyi tek tırnak içine alarak yeni Cset'ler oluşturulabilir, örneğin vowel := 'aeiou'.

Teller

Simge'de, dizeler karakter listeleridir. Bir liste olarak, bunlar jeneratörlerdir ve bu nedenle patlama sözdizimi kullanılarak yinelenebilirler:

 write(!"Hello, world!")

Dizenin her karakterini ayrı bir satıra yazdırır.

Alt dizeler, parantez içinde bir aralık belirtimi kullanılarak bir dizeden çıkarılabilir. Aralık belirtimi, bir noktayı tek bir karaktere veya dizenin bir dilimine döndürebilir . Dizeler sağdan veya soldan dizine eklenebilir. Bir dize içindeki konumlar , 1 A 2 B 3 C 4 karakterleri arasında olacak şekilde tanımlanır ve sağdan belirtilebilir −3 A −2 B −1 C 0

Örneğin,

 "Wikipedia"[1]     ==> "W"
 "Wikipedia"[3]     ==> "k"
 "Wikipedia"[0]     ==> "a"
 "Wikipedia"[1:3]   ==> "Wi"
 "Wikipedia"[-2:0]  ==> "ia"
 "Wikipedia"[2+:3]  ==> "iki"

Son örnek, bitiş konumu yerine uzunluk kullanmayı gösteriyorsa

Subscripting belirtimi olarak kullanılabilir lvalue bir ifade içinde. Bu, dizeleri başka bir dizeye eklemek veya bir dizenin bölümlerini silmek için kullanılabilir. Örneğin:

    s := "abc"
    s[2] := "123"
    s now has a value of "a123c"
    s := "abcdefg"
    s[3:5] := "ABCD"
    s now has a value of "abABCDefg"
    s := "abcdefg"
    s[3:5] := ""
    s now has a value of "abefg"

dizi tarama

Dizeleri işlemek için başka bir basitleştirme , bir dizideki işlevleri çağıran ile çağrılan tarama sistemidir ?:

 s ? write(find("the"))

Simge ?, öznenin sol tarafını ifade eder ve onu dize işlevlerine iletir. findİki parametre aldığını , birinci parametre olarak arama metni ve ikinci parametrede aranacak dizeyi hatırlayın . Kullanılması ?ikinci parametre örtülü olup programcı tarafından belirtilmesi gerekmez. Sırayla tek bir dizede birden çok işlevin çağrıldığı yaygın durumlarda, bu stil, ortaya çıkan kodun uzunluğunu önemli ölçüde azaltabilir ve netliği artırabilir. Simge işlevi imzaları, tanımlarında konu parametresini tanımlar, böylece parametre bu şekilde kaldırılabilir .

?Sadece sözdizimsel şeker biçimi değildir, aynı zamanda herhangi aşağıdaki dize işlemleri için "string tarama ortamı" kurar. Bu, iki dahili değişkene dayanır &subjectve &pos; içindeki mevcut konum veya imleç &subjectiken &pos, orijinal dizeye bir işaretçidir . Icon'un çeşitli dizgi işleme prosedürleri bu iki değişkeni kullanır, böylece programcı tarafından açıkça sağlanmaları gerekmez. Örneğin:

  s := "this is a string"
  s ? write("subject=[",&subject,"], pos=[",&pos,"]")

üretecekti:

subject=[this is a string], pos=[1]

Taranan dizi içinde hareket etmek için yerleşik ve kullanıcı tanımlı işlevler kullanılabilir. Tüm yerleşik işlevler varsayılan olarak &subjectve &postarama sözdiziminin kullanılmasına izin verecek şekilde olacaktır. Aşağıdaki kod, boşlukla ayrılmış tüm "kelimeleri" bir dizeye yazacaktır:

  s := "this is a string"
  s ? {                               # Establish string scanning environment
      while not pos(0) do  {          # Test for end of string
          tab(many(' '))              # Skip past any blanks
          word := tab(upto(' ') | 0)  # the next word is up to the next blank -or- the end of the line
          write(word)                 # write the word
      }
  }

Bu örnekte tanıtılan bir dizi yeni işlev vardır. posgeçerli değerini döndürür &pos. Bir kişinin neden bu işleve ihtiyaç duyduğu ve yalnızca &posdoğrudan değerini kullanmadığı hemen açık olmayabilir ; nedeni, bunun &posbir değişken olması ve bu nedenle &failprosedürün posalabileceği değeri alamamasıdır. Böylece pos, &posIcon'un hedefe yönelik akış kontrolünün, &pos. Bu durumda, test, Icon'un dize konumlarının tek numaralandırmasında satırın sonu olan "is & pos zero" dur. Eğer öyleyse değil sıfır, posdöner &failile ters çevrilir, notve döngü devam eder.

manygeçerli olandan başlayarak sağlanan Cset parametresinin bir veya daha fazla örneğini bulur &pos. Bu durumda, boşluk karakterleri aranır, bu nedenle bu işlevin sonucu, 'den sonra boşluk olmayan ilk karakterin konumudur &pos. örneğin, dizenin sonundan düşmesi durumunda yine bir potansiyelle o konuma tabhareket eder . esasen tersidir ; konumu, sağlanan Cset'ten hemen önceki konumu döndürür; bu, örneğin daha sonra başka bir . Alternasyon, bir satırın sonunda durmak için de kullanılır. &pos&failmanyuptomany&postab

Bu örnek, noktalar, virgüller ve diğer noktalama işaretlerinin yanı sıra sekme ve bölünmeyen boşluklar gibi diğer boşluk karakterlerini içerebilen daha uygun bir "kelime ayırma" Cset'i kullanılarak daha sağlam hale getirilebilir. Yani Cset sonra kullanılabilir manyve upto.

Daha karmaşık bir örnek, dil içinde oluşturucuların ve dizi taramanın entegrasyonunu gösterir.

 procedure main()
     s := "Mon Dec 8"
     s ? write(Mdate() | "not a valid date")
 end
 # Define a matching function that returns
 # a string that matches a day month dayofmonth
 procedure Mdate()
 # Define some initial values
 static dates
 static days
 initial {
        days := ["Mon","Tue","Wed","Thr","Fri","Sat","Sun"]
        months := ["Jan","Feb","Mar","Apr","May","Jun",
                  "Jul","Aug","Sep","Oct","Nov","Dec"]
 }
 every suspend   (retval <-  tab(match(!days)) ||     # Match a day
                             =" " ||                  # Followed by a blank
                             tab(match(!months)) ||   # Followed by the month
                             =" " ||                  # Followed by a blank
                             matchdigits(2)           # Followed by at least 2 digits
                 ) &
                 (=" " | pos(0) ) &                   # Either a blank or the end of the string
                 retval                               # And finally return the string
 end
 # Matching function that returns a string of n digits
 procedure matchdigits(n)
     suspend (v := tab(many(&digits)) & *v <= n) & v
 end

eleştiriler

Laurence Tratt, Icon üzerine, gerçek dünyadaki uygulamalarını inceleyen ve bir dizi endişe alanına işaret eden bir makale yazdı. Bunlar arasında, kökenlerinden sicim işlemeden türeyen ancak diğer alanlarda pek bir anlam ifade etmeyen bir dizi pratik karar vardı. Aralarında:

Prosedürlerin sonunda varsayılan olarak başarısız olma kararı, üreticiler bağlamında anlamlıdır, ancak genel prosedürler durumunda daha az anlamlıdır. Yukarıda belirtilen örneğe dönersek, write(f(-1))beklenen çıktı olmayacaktır. Yine de:

 x := 10
 (additional lines)
 x := f(-1)
 write(x)

10 yazdırılmasına neden olur. Bu tür bir sorun, etkileşimli bir hata ayıklayıcıda bile tüm kod çağrıldığı için xhiçbir zaman beklenen değeri almadığı için hiç açık değildir . Bu, programcıların herhangi bir dilde bilmesi gereken o "gaplardan" biri olarak reddedilebilir, ancak Tratt çeşitli Simge programlarını inceledi ve prosedürlerin büyük çoğunluğunun üretici olmadığını buldu. Bu, Icon'un varsayılan davranışının yapılarının yalnızca küçük bir azınlığı tarafından kullanıldığı, ancak diğerlerinde büyük bir potansiyel hata kaynağı oluşturduğu anlamına gelir.

Diğer bir sorun, bir boole veri türünün ve geleneksel boole mantığının olmamasıdır. Nihai hedefin bir değeri kontrol etmek olduğu çoğu durumda başarı/başarısızlık sistemi çalışır, ancak bu yine de görünüşte basit kodda bazı garip davranışlara yol açabilir:

 procedure main()
    if c then {
      write("taken")
    } 
 end

Bu program "alındı" yazacaktır. Bunun nedeni, testin cbir değer döndürmesidir; bu değer sıfırdır, aksi takdirde başlatılmamış tüm değişkenler için varsayılan değerdir. Sıfır geçerli bir değerdir, bu nedenle if cbaşarılı olur. Bunu çözmek için c == 0, kendi kendini belgeleyen koddan uzaklaşan testi açık hale getirmek gerekir - bunun "c sıfır mı" veya "c var mı" testi olup olmadığı belirsizdir.

Ayrıca bakınız

Notlar

Referanslar

alıntılar

bibliyografya

Dış bağlantılar