Polyglots oluşturmak için ipuçları


48

Bir 2 veya daha fazla farklı programlama dillerinde çalıştırılabilir bir programdır.

Çokgen yapmak veya belirli bir görev için çokgen yazmak kolay dilleri seçmek için hangi genel ipuçlarına sahipsiniz?

Lütfen çoğu durumda uygulanabilecek ipuçlarını gönderin. Yani, sadece iki özel dilden çokgenlerde çalışmamalılar. (Çok özel bir ipucunuz varsa, çok dilli bir soruya basit bir cevap gönderebilirsiniz.) Ancak, birçok dilde çalışmayı kolaylaştıran veya mevcut çokgenlere eklenmesini kolaylaştıran bir dilin özelliklerini sunabilirsiniz.

Lütfen cevap başına bir ipucu gönderin. Dile özgü bir ipucunun başka bir dil için de geçerli olup olmadığını belirtmekten çekinmeyin.

Yanıtlar:


25

Yorum sembollerini kullan

İki dilli bir çoklu dil oluşturmanın basit bir yolu, kodu iki bölüme şöyle ayırmaktır:

  1. İlk bölüm A dilindeki asıl işi yapar, B dilinde zararsızdır (hatasızdır) ve ikinci bölümü A diline gizleyen A dili yorum sembolünde biter.
  2. İkinci kısım, asıl işi B dilinde yapar.

Böylece

  • Dil A, işi yapan ilk kısmı ve ardından bir yorum görür.
  • B dili işe yaramaz bir ilk kısım, ardından ikinci kısmı görür.

Buradaki tek zor kısım, A dilinde iş yapan ve B dilinde hata yapmayan bir dizi açıklama (ilk kısım) bulmaktır. Bunun için bazı öneriler:

  • Yığın tabanlı dillerin çoğu, program sonunda yığının yalnızca üst kısmını görüntülemeye izin verir (bazen bu, 05AB1E'de olduğu gibi varsayılandır).
  • Bazı diller tanımsız ifadeleri görmezden gelir (örneğin Golfscript).

Bu yönergeleri kullanan basit bir örnek burada bulunabilir . A ve B dilleri sırasıyla MATL ve 05AB1E'dir .


24

İki boyutlu dilleri kullanın

Genellikle tüm kaynak kodunu ayrıştıran ve anlamadıkları şeyler üzerinde sözdizimi hataları veya istenmeyen çalışma zamanı efektleri üretecek tek boyutlu dillerin aksine (bu nedenle diğer dillerin kodlarını onlardan gizlemeye zorlarsınız), iki boyutlu diller yalnızca Yürütme yolundaki kod ayrıştırma, programın geri kalanının tamamen yok sayılması anlamına gelir. Yürütme yollarını birbirinden ayırmak için iki boyutta daha fazla alan var; Çok hızlı bir şekilde yoldan çıkarmak için talimat işaretçisini aşağı veya hatta sola (programın sağ tarafına sararak) alışılmadık bir yöne döndürebilirsiniz. Bir boyutlu dillerde faydalı olan teknikler ayrıca iki boyutlu dillere genelleştirilir (örneğin,;; Befunge-98’de, sadece IP’yi garip bir yöne göndermeye ek olarak), bunu tek boyutlu bir çözüme kıyasla daha katı bir kazanç haline getirmiştir.

Bonus olarak, iki boyutlu birçok dilin, programın sol üstünden başka bir giriş noktası vardır; bu, onları diğer dillerden ayırmak için herhangi bir çaba harcamanıza gerek kalmaması anlamına gelir; doğal olarak kendilerini gruptan ayırırlar.


20

Trues ve Sahte'lerinizi bilin

Her dil "doğru" ve "yanlış" ifadelerini biraz farklı bir şekilde görür. Benzer sözdizimlerine sahiplerse, dillerin farklı şekilde ele alacağına dair bir karar ekleyerek bundan yararlanabilirsiniz.

Trick veya Treat iş parçacığından bir örnek , ''boş bir dize kullanır . Lua'da bu, gerçeği değerlendirir, ancak Python'da sahtedir;

print(''and'trick'or'treat')

.. her dilde farklı bir dize basacaktır.

Tek gereken, böyle bir değer bulmak. Örneğin, PHP'de ancak Python'da '0'değerlendiren kullanabilirsiniz .falsetrue


17

En az bir dilde blok alıntılar

İşte Python ve C ++ 'da çalışan bir örnek

#include <iostream> /*
""" */
int main() {
    std::cout << "Hello World!\n";
}

/* """
print("Hello World!")
# */

Luis Mendo , yorum kullanmanın en kolay çözümü olduğunu düşündüğüm şeyi belirledi.

Yorum engelleyen bir dilden ve birincisinde düzenli sözdiziminin, ikincisinde sözdizimini yorumladığı başka bir dili ararsınız.

Daha da kolay olanı, birbiriyle değiştirilebilir şekilde doğru sözdizimi olan farklı blok yorum stillerine sahip iki dildir, ancak kontrol etmekten rahatsız olmadım.

Python 3.5 ve C ++ ile göz atın


2
İlk satırda noktalı virgül olmamalıdır.

Doğru. İyi nokta
deksgecko

15

Böl ve fethet

Çok dilde çok dilli bir yazı yazarken, tüm dilin kontrol akışlarını derhal birbirinizden ayıramazsınız. Bu nedenle, bazı dillerin bir kısmını belirli bir süre "gerçek çok dilli" olarak yazmanız ve aynı kodun her birinde çalışmasına izin vermeniz gerekir. Bunu yaparken aklınızda bulundurmanız gereken iki ana kural vardır:

  • Herhangi iki dilde kontrol akışı ya çok benzer ya da çok farklı olmalıdır . Çok sayıda birleştirilmiş yapraklı kontrol akışını kullanmaya çalışmak, kafanızın karışması için bir reçetedir ve programınızın değiştirilmesini zorlaştırır. Bunun yerine, aynı yerde bulunan tüm programların aynı sebepten dolayı orada olmasını ve ihtiyaç duyduğunuz sürece mutlu bir şekilde paralel olarak çalıştırılabilmesini sağlayarak yapmanız gereken iş miktarını sınırlamanız gerekir. Bu arada, eğer bir dil diğerlerinden çok farklıysa, yürütmesinin mümkün olan en kısa sürede çok farklı bir yere taşınmasını istersiniz, böylece kodunuzu aynı anda iki farklı sözdizimsel modele uygun hale getirmeye çalışmak zorunda kalmazsınız.

  • Bir dili veya benzer bir dil grubunu birbirinden uzağa bölme fırsatlarını arayın. Daha büyük gruplardan daha küçük gruplara çalışın. Programda belirli bir noktada benzer dillerden oluşan bir grubunuz olduğunda, bunları bir noktada ayırmanız gerekir. Programın başında, #yorum işaretçisi olarak kullanılan dilleri, başka bir yorum işaretçisi kullanan dillerden ayırmak isteyebilirsiniz . Daha sonra, belki de tüm dillerin f(x)işlev çağrıları için sözdizimi kullandığı , noktalı virgüllü komutları ayırdığı ve benzer sözdizimsel benzerliklerinin olduğu bir noktaya sahipsiniz. Bu noktada, onları bölmek için dile özgü bir şey kullanabilirsiniz, örneğin Ruby ve Perl'in ''dizelerde kaçış dizileri işlememesi, ancak Python ve JavaScript kullanması gibi.

Genel olarak, programınızın mantıksal akışı birbiri ardına benzer dil gruplarına tekrar tekrar bölünerek bir ağaç gibi bitmelidir. Bu, poliglotu yazmadaki zorluğun çoğunu başlangıçta ilk bölünmeden önce sağa koyar. Kontrol akışı gittikçe daha fazla yayıldıkça ve herhangi bir noktada çalışan diller gittikçe daha fazla benzerleştikçe, göreviniz kolaylaşıyor çünkü sözdizimi hatasına karışan dillere neden olmadan daha gelişmiş sözdizimi kullanabilirsiniz.

İyi bir örnek {JavaScript, Ruby, Perl, Python 3}; tüm bu diller, işlev çağrılarını parantez içinde kabul eder ve ifadeleri noktalı virgüllerle ayırabilir. Hepsi de evaletkili bir şekilde akış kontrolü yapmanızı sağlayan portatif bir ifadeyi destekliyor . (Perl, gruptan erken ayrılmak için bu dillerin en iyisidir, çünkü diğerlerinden değişkenler için farklı bir sözdizimi vardır.)


13

Dize değişmezleri içindeki kodu gizle

Çoğu dilde, bir dizgenin kendisi değişmez ya hiçbir şey yapmaz ya da kolayca ters çevrilebilecek bir şey yapar (dizeyi yığının üzerine itmek gibi). Dize değişmezi sözdizimi, özellikle birçok dilin gömülü yeni satırlı dizeleri işlemek için kullandığı alternatif sözdizimleri için nispeten standartlaştırılmamıştır; örneğin, Python var """ ... """, Perl var q( ... )ve Lua var [[ ... ]].

Bunların iki ana kullanımı var. Birincisi, bir dilin ilk bölümünün sonunda bir dize başlayarak ve ikinci dize başında devam ederek bir dize başlayarak farklı dillere yönelik bölümleri birleştirmenize izin vermektir: dize çeşitliliği nedeniyle dizginin yanlışlıkla kapatılmasını önlemek oldukça kolaydır. dize sınırlayıcıları farklı diller arasında. Diğeri, birçok dize sınırlayıcısının, diğer dillerde (genellikle yorum işaretçilerinden çok daha fazla) bir komut olarak anlamlı olduğu anlamına gelir; bu nedenle x = [[4] ], listeler için JSON gösterimini kullanan, ancak listelerde başlayan dillerde zararsız bir atama olan bir şey yapabilirsiniz. Lua'da bir dize (ve böylece Lua kodunu diğerlerinden ayırmanıza olanak tanır, etkili bir şekilde diğerine atlar ]]).


13

Programı sonlandırmak

Programı bir dilde aniden sona erdirebilirsiniz, böylece kodu başka bir dilde yoksayırsınız.

Yani temelde bu format kullanılabilir

code_in_language1 end_program_in_language1 code_for_language2 end_program_in_language2 ...

end_program_in_languageNprogramı sonlandırma komutu nerede ?

Mesela şükran günü için ne getireceksin? , Programı Dip'te sonlandırdım ve Dip tercümanı görmezden gelmek için başka bir dil olan V kodunu yazdım.

"turkey"e#"corn"??"gravy"p&Ssalad
"turkey"e#"corn"??"gravy"                 
                         p&            # print stack and exit program (Dip) 
                           Ssalad      # Now that the program ended in Dip,
                                       # I can write V code that would otherwise
                                       # have caused errors in Dip

Ancak o zaman, tüm dillerin programı bu şekilde sonlandırabilecek bir komutu yoktur. Ancak, eğer böyle bir dil özelliği varsa, akıllıca kullanılmalıdır.

@LuisMendo'nun önerdiği gibi, eğer dilde yerleşik bir "son program" yoksa, programı sonlandırmak için bir hata oluşturabilirsiniz (eğer izin verilirse).


2
Dilin programı sonlandıracak bir işlevi veya ifadesi olmasa bile, genellikle bir hata olur
Luis Mendo

1
@LuisMendo: Anlaşılan, birçok poliglot probleminin özellikle çıkış-çökmesini yasakladığını, çünkü işleri çok kolaylaştırdığını belirtti. Yine de, kullanmadıkları zaman istifade etmek iyi bir fikirdir.

1
Muhtemelen ikinci bölümün kodunun ilk dilde sözdizimsel olarak doğru olması gerektiğini söylemelisiniz, aksi takdirde çoğu pratik dil hata yapar.
MilkyWay90

13

Dize değişmezleri içindeki değişken veya kod

Çift tırnaklı dizgi değişmezleri birçok dilde çoğunlukla zararsızdır. Ancak bazı dillerde kod da içerebilir.

Bash'de kullanabilirsiniz `...`(programı sonlandırmaz):

"`echo Hello world! >/proc/$$/fd/1`"

Tcl’de şunları kullanabilirsiniz [...]:

"[puts {hello world!};exit]"

PHP'de kullanabilirsiniz ${...}(Bash'de bir hata oluşturur, bu yüzden Bash kodundan sonra görünmesi gerekir):

"${die(print(Hello.chr(32).world.chr(33)))}";

Ruby'de şunları kullanabilirsiniz #{...}:

"#{puts 'Hello world!';exit}"

Başkaları da olabilir.

Bu gramerler uyumlu değil. Bu, bu dillerin tüm kodlarını tek bir dizeye zararsız bir yere koyabileceğiniz anlamına gelir. Ve diğer dillerde tanınmayan kodu görmezden gelecek ve bunları dize içeriği olarak yorumlayacaktır.

Çoğu durumda, orada kolayca bir çift alıntı karakter yorum ve daha geleneksel bir çokgen yapmak.


12

Değişken Takma Ad

Muhtemelen bu kadar çok dile ulaşabildiğinden, muhtemelen en basit (IMO) en önemli püf noktalardan biridir.

Örnek:

print=alert;print("Hello World!")

Bu sadece Javascript değil aynı zamanda Python, Ruby, vb. İle de çalışacaktır. Tabii ki, yorum önerileri / yazı düzenlemeleri kabul edilir.


5
Not örn JS / Python yaparken, bu takma genellikle daha kısa olduğunu alertiçin printPython (3 only) içinde JS en comment sözdizimi, çünkü //Python en olurken, kolayca bir Python programı işlenebilir #JS içine çalışmış edilemez.
ETHproductions

11

#tabanlı yorumlar

Bu ipucu, en az bir dilde Exploit yorum sembolleri ve Blok alıntıların bir alt kümesidir.

Pek çok dilde, özellikle de esolangs yerine üretime hazır diller içeren çokgenler oluştururken, #blok veya tek satırlık yorumlarda kullanılan dillere bakmak yararlı olabilir .

  • İle başlayan blok yorum sözdizimlerini içeren birçok dil #vardır ve aşağıdaki karakterlerde çok fazla çeşitlilik vardır #.
  • Bu dillerin çoğu aynı zamanda tek #bir satır yorumuna da izin verir; bu , bir dilde blok yorum başlatabilecek bir şeyin bir başkasının sıradan bir yorum olduğu anlamına gelir;

İşte #blok yorumda kullanılan dillerin kısa bir özeti listesi (ayrıntılı değil):

Language            Start       End      Single-line #?     Notes
------------------------------------------------------------------------------------------
Agena               #/          /#             ✓
AutoIt              #cs         #ce
Brat                #*          *#             ✓
C                   #if 0       #endif                      Not actually a comment
CoffeeScript        ###         ###            ✓            Needs to be on separate line
Common Lisp         #|          |#
Julia               #=          =#             ✓
Lily                #[          ]#             ✓
Objeck              #~          ~#             ✓
Perl 6              #`{         }#             ✓            Any bracketing chars will do
Picolisp            #{          }#             ✓
Scheme              #|          |#

Daha fazla örnek için Rosetta Kodu'na bakınız .

İşte bir gösteri olarak hızlı ve kolay bir örnek:

#|
###
#`[

print("Julia")
#=

|#
(format t "Common Lisp")
#|

###
alert("CoffeeScript")
###

]#
say "Perl 6"
#`[

...

# ]# # ### # |# ; =#

Zephyr var #- ... -#.
DLosc

11

Aritmetik operatör farklılıkları

Benzer diller veya basit çokgenler için, bazen dillerin aritmetik performansındaki farklılıkları araştırmak yararlı olabilir. Bunun nedeni çoğu (ezoterik olmayan) dillerin infix aritmetik operatörlerine sahip olmalarıdır ve aritmetik bir fark yaratmanın hızlı ve kolay bir yolu olabilir.

Örneğin:

  • ^ bazı dillerde bitsel XOR, bazılarında üstel
  • / bazı dillerde tamsayı, diğerlerinde kayan nokta bölümüdür.
    • Tamsayı bölme diller için -1/2olan -1bir dil (yuvarlak aşağı) ve 0diğerlerinde (sıfıra yuvarlak)
  • -1%2olduğu -1bazı dillerde ve 1diğerlerinde
  • --x bazı dillerde no-op'tur (çift olumsuzlama) ve bazılarında ön azaltma
  • 1/0 Bazı dillerde sonsuzluk, bazılarında ise hata verir
  • 1<<64bazı dillerde 0 (taşma) ve verir 36893488147419103232diğerlerinde

3
x=1;["JS","Python"][--x]Çalıştığı dilin adını (JS ve Python arasında) döndüren basit bir örnek olacaktır .
ETHProductions,

10

Brainfuck Kullan

Hemen hemen tüm BF uygulamaları +-<>[].,, bizim lehimize çalışacak olan olmayan karakterleri ortaya koyuyor !

BF ilk önce BF bölümünü yazdığınız sürece , muhtemelen bu özellik nedeniyle çok dilde çalışmak için en kolay dillerden biridir . BF kodunuzu yazdıktan sonra, sadece BF yapısı etrafında sahip olduğunuz diğer kodları modelleme meselesidir .

İşte gerçekten basit bir örnek:

.+[.+]

Bu oldukça fazla artışlar ve kod çıkışı "sonsuza kadar" (çalışma zamanı ayarlarına bağlı olarak). Şimdi, rastgele bir kod parçası yazmak istiyorsanız, JS'de yapabileceklerinizi söyleyin:

x=>"asdf".repeat(+x)[x*Math.random()*2+1|0]

JS'nin BF etrafında kalıplandığına dikkat edin.

BF ile başlamaya gerçekten hazırsanız, bunun en iyi şekilde çalıştığını bildiğinizden emin olun; Başka bir dille başlamak ve BF'yi dahil etmeye çalışmak oldukça zordur.


6
BF'nin entegrasyonundan birkaç baytlık tasarrufun fazla bir faydası olmadığı daha büyük poligonlar için, BF'yi en son yazıp diğer kodu []gerektiği kadar sarardım.
Sp3000

6
Bu sadece beyin avı için değil, aynı zamanda çok fazla beyin avı benzeri dil ve bir çok diğer Turing tarp için de geçerlidir.
0

2
İlki x=>, bu durumda önemli olmayan hücreyi değiştirdi, ama sadece söylemek istedim
Roman Gräf

7

Çoğu karakterin önemli olmadığı dilleri kullanın

Bu, Mama Fun Roll’un BF hakkındaki geneline bir genellemedir . Çok karakterleri yok sayan bir esolang, çokgenlerde çok faydalıdır. Ayrıca faydalıdır: İçinde çok sayıda karakterin birbiriyle değiştirilebildiği bir esolang. Bazı örnekler:

  • Boşluk , boşluk, sekme veya yeni satır olmayan her şeyi yok sayar.
  • Brain-Flak temelde herşeyi görmezden geliyor ()[]{}<>. ( @bazen tercüman onu bir hata ayıklama bayrağının başlangıcı olarak ayrıştırmaya çalıştığında hataya neden olur.)
  • o KODU harfleri dışında her şeyi görmezden gelir. Ayrıca, tüm küçük harfler, tümü büyük harflerle olduğu gibi değiştirilebilir.
  • Wierd, yalnızca boşluk ile boşluk olmayan karakterler arasında ayrım yapar.
  • In wordy , bazı noktalama karakterleri dikkate alınmaz ve tüm harfler birbirleriyle değiştirilebilir.
  • Hem Parantez hem de Parantez Cehennemi parantez dışındaki her şeyi görmezden gelir.

Bu @hatayı düzelttim .
Buğday Sihirbazı,

Python ile Whitespace birleştirerek deneyin
enedil

@enedil Python ile sekmenize sahip olmanıza gerek yok. Kullanabilirsinizexec('''...\t\n\40''')
MilkyWay90

5

Yuvalanmış Blok Yorumlarından Haberdar Olun

Bazen birden çok dil, blok yorumlar için aynı sözdizimini kullanır; bu, iki dilde çok dilli bir grup oluşturmak için bir anlaşma kesicisinden daha sık değildir. Ancak, çoğu zaman, dillerden biri, ayrı kod yolları oluşturmak için kötüye kullanılabilecek iç içe blok yorumlara izin verecektir.

Örneğin, bu polyglot'u düşünün:

#[#[]#print("Lily")#]#echo"Nim"

Nim ve Lily hem blok yorumları kullanır #[ve hem de ]#blok yorumları başlatır ve bitirir, ancak yalnızca Nim iç içe blok yorumlara izin verir.

Lily #[, ikinciyi tekil blok yorumunun bir parçası ve ilkini ]#blok yorumunu sonlandırır. ( #Aşağıdaki Lily'nin print ifadesi, Nim'in kodunu gizleyen bir çizgi yorumudur.)

Alternatif #[]#olarak, iç içe geçmiş (boş da olsa) blok yorumu ve print("Lily")#dış blok yorumu olarak görür.


4

Bu sayılır mı emin değilim, ama ...

Her şeyi geçerli bir perlprograma dönüştürmek için bir shebang hattı kullanın

Göre bu cevap size herhangi bir dosyayı geçirirseniz ve Perl dokümantasyon, bir shebang hattı ile başlar o perl, onu çalıştırmak için uygun programı çağırır. Örneğin, bu

#!/usr/bin/python

for i in range(6):
    print i**2

Eğer ararsanız Python yorumlayıcısı tarafından yürütülür perl filename.py.


3
Program çağrılabilirken perl, Perl programı haline gelmez.
Palo Ebermann

2
@ PaŭloEbermann Sınırda olduğunun farkındayım, bu yüzden cevabımı "sayılıp sayılmadığından emin değilim" ile başladım. :) Fakat "Perlinde ne yazılır ve referans uygulaması tarafından döndürülür" değilse gerçek Perl'i ne tanımlar perl? İyi bir filosoraptor meme gibi geliyor ...
Federico Poloni


4

Var olmayan işlevleri çağırın, sonra argümanlarını değerlendirirken çıkın

Birçok programlama dili, içinde ifadeleri olan bir çift parantezin ardından rastgele bir tanımlayıcıyı ayrıştırma yeteneğine sahiptir:

identifier(1 + 1)

Bazen, kullandığınız farklı bir dile kod vermeniz gerektiğinden, söz konusu tanımlayıcının formu düzeltilebilir. Tanımlayıcı, dilin gerçekte sahip olduğu bir işleve karşılık gelmiyorsa, bu başlangıçta sorun çıkarmış gibi görünebilir.

Bununla birlikte, birçok programlama dili, bir işlevin argümanlarını, işlevin gerçekten var olup olmadığını kontrol etmeden önce değerlendirir (örneğin Lua) ve bu şekilde herhangi bir yapıyı kullanabilirsiniz; İhtiyacınız olan tek şey, programın işlevinin argümanlarının içindeki bir yerden çıkmasıdır.

İşte bir örnek, bir dc / Lua polyglot:

c2pq(1 + #os.exit(print(3)))

c2pq2 yazdırmak ve çıkmak için bir dc programıdır; Lua bunu bir fonksiyonun adı olarak görür, ancak Lua'nın argümana bir çıkış komutu yerleştirerek hata yapması önlenebilir. Bu yapının en büyük avantajı, bir atamanın ( c2pq =) aksine , değişken isimlerinin sigil ile başladığı dillerle otomatik olarak uyumsuz olmasıdır; İşlev adı sözdizimi, diller arasında değişken ismi sözdiziminin olduğundan çok daha tutarlıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.