Loop tanpa 'looping' [tertutup]

85

Sebuah pertanyaan yang mirip dengan ini telah diajukan beberapa tahun yang lalu , tetapi yang ini lebih rumit.

Tantangannya sederhana. Menulis sebuah program (dalam bahasa pilihan Anda) yang berulang kali mengeksekusi kode tanpa menggunakan struktur pengulangan seperti while, for, do while, foreachatau goto( Jadi untuk semua nitpickers Anda, Anda tidak dapat menggunakan loop ). Namun, rekursi tidak diperbolehkan, dalam fungsi yang menamakan dirinya sendiri (lihat definisi di bawah) . Itu akan membuat tantangan ini terlalu mudah.

Tidak ada batasan pada apa yang perlu dieksekusi dalam loop, tetapi posting penjelasan dengan jawaban Anda sehingga orang lain dapat memahami dengan tepat apa yang sedang dilaksanakan.

Bagi mereka yang mungkin terpaku pada definisi, definisi loop untuk pertanyaan ini adalah:

A programming language statement which allows code to be repeatedly executed.

Dan definisi rekursi untuk pertanyaan ini akan menjadi definisi fungsi rekursif standar Anda:

A function that calls itself.

Pemenang akan menjadi jawaban yang paling banyak mendapat dukungan pada 16 Juli pukul 10 pagi waktu bagian timur. Semoga berhasil!

MEMPERBARUI:

Untuk menenangkan kebingungan yang masih diungkapkan ini dapat membantu:

Aturan sebagaimana dinyatakan di atas:

  • Jangan gunakan loop atau goto
  • Fungsi tidak bisa menyebut diri mereka sendiri
  • Lakukan apa pun yang Anda inginkan di 'lingkaran'

Jika Anda ingin menerapkan sesuatu dan aturannya tidak secara eksplisit melarangnya, silakan dan lakukan. Banyak jawaban sudah melanggar aturan.

CailinP
sumber
27
Bagi mereka yang menginginkan trik mudah, saya tidak dapat repot mempostingnya: P Hanya membuat 2 fungsi, function Apanggilan function Bdan function Bpanggilan function Asementara 1 fungsi melakukan sesuatu. Karena fungsi tersebut tidak menyebut dirinya sendiri, fungsi tersebut harus valid berdasarkan kriteria ^. ^
Teun Pronk
2
"Berubah ke kontes popularitas untuk fokus pada kreativitas" Mengubah pertanyaan itu curang!
CousinCocaine
4
Definisi "rekursi" tidak terlalu berguna. Akan lebih baik untuk melarang fungsi rekursif , yang merupakan fungsi yang merujuk pada diri mereka, secara langsung atau tidak langsung.
lrn
3
Yang tidak jelas adalah "definisi" loop constructor dan rekursi. Tidak ada yang sangat tepat. Contoh: rep(f){f();f();}- ini adalah pernyataan (pernyataan fungsi adalah pernyataan dalam beberapa bahasa) yang memungkinkan mengeksekusi kode berulang kali. Apakah itu dilarang. Anda meminta kode untuk mengimplementasikan loop. Jika kode itu secara sintaksis merupakan pernyataan, Anda baru saja menolaknya. Contoh lain: f(b) { b(); g(b); }; g(b) { f(b); }. Saya akan mengatakan fadalah fungsi rekursif (dengan menjadi saling rekursif dengan g). Apakah itu dilarang?
lrn
3
@CailinP, apa yang saya " menutup telepon " adalah bahwa pertanyaan di situs harus pada topik untuk situs: yang berarti memiliki, spesifikasi tujuan yang jelas, yang pertanyaan ini tidak.
Peter Taylor

Jawaban:

258

Rubi

def method_missing(meth,*args)
  puts 'Banana'
  send(meth.next)
end

def also
  puts "Orange you glad I didn't say banana?"
end

ahem

Demo

Bersihkan tenggorokannya, mencetak "Pisang" 3070 kali, dan juga menempatkan "Oranye, kau senang aku tidak mengatakan pisang?".

Ini menggunakan fungsi definisi metode just-in-time yang konyol dari Ruby untuk mendefinisikan setiap metode yang secara alfabetis terletak antara kata 'ahem' dan 'juga' ("ahem", "ahen", "aheo", "ahep", "ahep", "aheq", "aher", "ahes", "ahet", "aheu", "ahev" ...) untuk pertama-tama mencetak Pisang dan kemudian memanggil yang berikutnya dalam daftar.

histokrat
sumber
4
Akhirnya hits "juga", yang didefinisikan, dan karena itu tidak hilang.
histokrat
77
Ini histeris.
Michael B
4
@ barrycarter: Dalam Ruby,, String#nextyang disebut dalam method_missingfungsi kurang lebih seperti menambahkan 1 ke nomor kecuali ia bekerja dengan semua karakter alfanumerik (dan non-alnums jika mereka adalah satu-satunya karakter dalam string). Lihat ruby-doc.org/core-2.1.2/String.html#method-i-next
3Doubloons
2
@NickT itu dapat digunakan di kelas-kelas seperti pembangun XML di mana Anda dapat membuat tag hanya oleh b.my_tag. Ini juga digunakan dalam model ActiveRecord atau OpenStruct. Dalam 'Wat talk' dia mengatakan bahwa global method_missingitu buruk, tetapi cakupannya luar biasa.
Hauleth
2
Saya ingat komentar lama di program ruby ​​lain: "Saya suka itu karena ia punya meth"
vidya sagar
82

Python - 16

atau bahasa lain dengan eval.

exec"print 1;"*9
Vektor
sumber
Bisakah Anda menggambarkan apa yang program Anda lakukan?
CailinP
10
Dibutuhkan string ( "print 1;"), duplikatnya 9 kali ( *9), kemudian jalankan string yang dihasilkan ( exec). Mengulang sepotong kode tanpa benar-benar berulang sama sekali.
scragar
12
Yay untuk perkalian string!
Thane Brimhall
2
Juga bekerja di Ruby jika Anda mengubah execke eval atau yang printke echo.
Ajedi32
80

CSharp

Saya telah memperluas kode menjadi cara yang lebih mudah dibaca karena ini bukan lagi kode golf dan menambahkan penghitung kenaikan sehingga orang dapat benar-benar melihat bahwa program ini melakukan sesuatu.

class P{
    static int x=0;
    ~P(){
        System.Console.WriteLine(++x);
        new P();
    }
    static void Main(){
        new P();
    }
}

(Jangan pernah melakukan ini).

Pada awal kita membuat instance baru dari Pkelas, yang ketika program mencoba untuk keluar memanggil GC yang memanggil finalizer yang membuat instance baru Pkelas, yang ketika mencoba untuk membersihkan menciptakan baru Pyang memanggil finalizer .. .

Program akhirnya mati.

Sunting: Secara misterius ini hanya berjalan sekitar 45 ribu kali sebelum mati. Saya tidak tahu bagaimana GC menemukan loop tak terbatas saya yang rumit tapi ternyata berhasil. Singkatnya sepertinya tidak mengetahuinya dan utas baru saja terbunuh setelah sekitar 2 detik eksekusi: https://stackoverflow.com/questions/24662454/how-does-a-garbage-collector-avoid-an -infinite-loop-sini

Sunting2: Jika Anda pikir ini agak terlalu mirip rekursi pertimbangkan solusi saya yang lain: https://codegolf.stackexchange.com/a/33268/23300

Ini menggunakan reifikasi metode generik sehingga pada saat runtime itu terus-menerus menghasilkan metode baru dan masing-masing metode dalam istilah panggilan metode yang baru dicetak. Saya juga menghindari menggunakan referenceparameter tipe, karena biasanya runtime dapat membagikan kode untuk metode tersebut. Dengan valueparameter tipe, runtime dipaksa untuk membuat metode baru.

Michael B
sumber
20
Saya bahkan tidak tahu C # memiliki destruktor. +1 untuk mengajari saya.
seequ
4
@TheRare, memang benar tetapi sifatnya non-deterministik dan mungkin tidak pernah dipanggil selama eksekusi program. Mereka diimplementasikan sebagai pengganti metode virtual Finalizesehingga mereka kadang-kadang dipanggil finalizer. Dalam C # nyata, Anda harus menggunakan IDisposablepola.
Michael B
Sepertinya ada time-out yang terjadi di beberapa titik. Saya tidak berpikir itu adalah GC yang menghentikan siklus Anda, tetapi sebaliknya sistem operasi memutuskan bahwa program Anda terlalu lama untuk berakhir.
LVBen
Saya pikir ini benar-benar runtime yang memutuskan untuk membunuh program belum tentu OS. Thread pengumpul sampah yang dipanggil pada akhir program diberi batas waktu tetap ~ 2 detik sebelum dimatikan.
Michael B
Dengan beberapa modifikasi kecil (tidak membiarkan program berakhir, melepaskan objek P pertama ke GC, dan berulang kali memanggil GC.Collect), saya bisa menjalankannya tanpa batas.
LVBen
53

Dibalik

.

Befunge tua yang baik menghasilkan 0 (dari tumpukan kosong) cukup lama, karena garis membungkus.

Le Canard fou
sumber
1
Ha! Saya suka trik seperti ini
CailinP
47

JS

(f=function(){ console.log('hi!'); eval("("+f+")()") })()

Berfungsi menyenangkan!

Fungsi yang membuat fungsi lain dengan tubuh yang sama dengan dirinya sendiri dan kemudian menjalankannya.

Ini akan menampilkan hi di akhir ketika batas stack tercapai dan semuanya runtuh.

Penafian: Anda tidak akan dapat melakukan apa pun di browser Anda sampai batas tumpukan tercapai.


Dan satu lagi, lebih jahat :

function f(){ var tab = window.open(); tab.f = f; tab.f()}()

Itu menciptakan fungsi yang membuka jendela, lalu menciptakan fungsi di dalam jendela itu yang merupakan salinan dari fungsi, dan kemudian menjalankannya.

Penafian: jika Anda mengizinkan popup dibuka, satu-satunya cara untuk menyelesaikannya adalah dengan memulai ulang komputer Anda

eithed
sumber
5
Ini sangat jahat tentunya;)
CailinP
28
@ CailinP Cukup eval pasti.
seequ
Saya pikir Anda kehilangan sebuah fdi akhir fungsi kedua Anda. Itu harus }f()pada akhirnya.
Chirag Bhatia - chirag64
2
Sayangnya, saya menyadarinya karena saya mencobanya. : P
Chirag Bhatia - chirag64
7
-1 - ini hanya rekursi.
user253751
39

x86 assembly / DOS

    org 100h

start:
    mov dx,data
    mov ah,9h
    int 21h
    push start
    ret

data:
    db "Hello World!",10,13,"$"

Apakah saya mengatakan tidak ada rekursi ekor terbalik ? Benarkah saya? Madame mim naga ungu

Bagaimana itu bekerja

The retinstruksi, digunakan untuk kembali dari fungsi, sebenarnya muncul alamat pengirim dari tumpukan (yang biasanya diletakkan di sana oleh yang sesuai call) dan melompat untuk itu. Di sini, di setiap iterasi kami pushalamat entrypoint pada stack sebelum kembali, sehingga menghasilkan loop tak terbatas.

Matteo Italia
sumber
Saya bertanya-tanya apakah ini mungkin dilakukan dalam pertemuan.
Ian D. Scott
2
Berantakan dengan tumpukan yang membahayakan Anda . Di sini ada naga ;-)
Trauma Digital
1
Saya akan memanggil codegolf.stackexchange.com/a/34295/11259 sebagai duplikat yang satu ini, tapi saya melihat itu sebenarnya jawaban sebelumnya
Digital Trauma
@DigitalTrauma: ya, saya perhatikan setelah saya memposting entri saya, tetapi saya harus melampirkan foto Nyonya Mim. :-) Untungnya ada beberapa perbedaan (miliknya sedikit lebih dikaburkan dan bekerja pada Linux 32 bit, milik saya dimainkan langsung di DOS dan tidak ada lompatan lain), jika tidak ada yang keberatan saya akan meninggalkan ini di sini.
Matteo Italia
@MatteoItalia Tidak dikaburkan, hanya jelek;) (tho "tambah eax, 4" juga membingungkan saya, saya tidak bisa menemukan tabel ukuran opcode jadi saya hanya menebak-nebak ukurannya). Saya membuatnya dalam kompiler online ketika proyek pekerjaan saya sedang dikompilasi sehingga terlihat mengerikan. Ide bagus menggunakan "start:".
PTwr
37

Jawa

Langsung dari XKCD

Ikatan

Ini adalah permainan tangkapan tanpa akhir antara orangtua dan anak!

Target CHILDdiatur ke PARENTdan target PARENTadalah CHILD. Ketika PARENTpanggilan AIM, itu melempar instance dari BALLkelas dan itu ditangkap oleh pernyataan tangkapan. Pernyataan tangkapan kemudian memanggil di PARENT.TARGET.AIMmana targetnya adalah CHILD. Mesin CHILDvirtual melakukan hal yang sama dan "melempar bola kembali" ke induk.

Kirk Backus
sumber
3
Saya suka komik itu!
Derek 朕 會 功夫
1
Akan lebih baik jika bola itu benar-benar dilemparkan antara orang tua dan anak. Seperti adanya, bola selalu dilempar dan ditangkap oleh "orang" yang sama.
Ajedi32
@ Ajedi32 Akan benar-benar muncul itu melempar bolak-balik; TARGET Orangtua adalah anak, dan target anak adalah orang tua. Aim dipanggil oleh orang tua, yang meronta-ronta bola dan menyuruh anak membidik dan melempar bola, cue loop
Alex Coleman
12
@AlexColeman Kode ini analog dengan orang tua yang melempar bola ke udara, menangkapnya, lalu memberikannya kepada anak yang melakukan hal yang sama sebelum mengembalikan bola ke induknya, dan seterusnya.
Ajedi32
11
Perintah TARGET.AIM(B);dalam metode AIMadalah panggilan rekursif. Jadi ini melanggar aturan "fungsi tidak bisa menyebut diri mereka".
Theodore Norvell
31

Bash, 3 karakter

yes

ya akan berulang kali mengembalikan 'y' ke konsol

Sunting: Semua orang didorong untuk mengedit baris ini:

yes something | xargs someaction

(terima kasih kepada Olivier Dulac)

SepupuCocaine
sumber
1
Mengapa ini terus berjalan? Saya tidak mempertanyakannya hanya mencoba mencari tahu mengapa.
Teun Pronk
2
@TeunPronk yesadalah perintah bash yang mencetak kata ya hingga terbunuh atau aliran menjadi tertutup. Jika itu menulis ke layar itu tidak akan pernah berhenti sampai Anda membunuhnya Ini agak curang, karena itu adalah perintah yang pada dasarnya terdiri dari loop over printf.
scragar
1
Lebih menyenangkan akan digunakan yesuntuk membuat loop lainnya tetap berjalan.
trlkly
3
@izkata: tetapi kemudian Anda dapat:: yes something | xargs someactiontanpa rekursi (Anda bahkan dapat menambahkan -n 1 ke xargs hanya memiliki 1 "sesuatu" per baris, dll). Menggunakan xargs membuka jalan bagi perilaku yang lebih kompleks (bahkan mereka yang tidak memiliki hubungan sama sekali dengan output ya)
Olivier Dulac
4
@scagar Anda harusnya baru saja menjawab yes.
daviewales
28

C, 35 karakter

main(int a,char**v){execv(v[0],v);}

Program mengeksekusi sendiri. Saya tidak yakin apakah ini dianggap rekursi atau tidak.

kwokkie
sumber
4
@mniip Tail rekursi, kemudian, jika diterapkan pada level proses
Izkata
3
@Izkata Ekor rekursi masih rekursi, tapi ini bukan rekursi. Rekursi menyiratkan suatu fungsi (atau proses dalam kasus ini) 'menunggu' untuk iterasi lain dari dirinya sendiri untuk berakhir. Dalam hal ini, execmenyebabkan proses baru untuk menggantikan yang asli, sehingga tidak ada tumpukan panggilan yang pada akhirnya akan kembali atau meluap.
milinon
4
@ millinon Dalam bahasa yang mendukung optimisasi, rekursi ekor menggantikan panggilan sebelumnya di tumpukan panggilan, mirip dengan bagaimana execmenggantikan proses sebelumnya. Itu juga tidak akan meluap.
Izkata
1
@ Millinon hanya untuk menjadi super pedantic dan untuk menarik diskusi ini lebih lama, dalam bahasa pemrograman Skema, optimasi ini adalah fitur bahasa. Ada dalam spesifikasi bahwa jika Anda membuat panggilan ekor-rekursif, juru bahasa / kompiler harus menggunakan kembali bingkai tumpukan terakhir. Ini karena Skema tidak memiliki struktur looping bawaan, jadi satu-satunya cara untuk mengimplementasikan loop dalam Skema adalah dengan melakukan rekursi ekor, dan itu akan agak menyebalkan jika Anda mendapat stack overflows karena mencoba mengulang terlalu sering :)
Ord
2
Jika Anda ingin pedantry, Skema tidak memiliki "optimisasi panggilan tail", ia memiliki "panggilan ekor yang tepat". Ini bukan optimasi, ini adalah persyaratan dasar dari standar bahasa dan gagal untuk memasok itu tidak diizinkan, jadi "optimasi" (atau saran bahwa itu ada hubungannya dengan rekursi) adalah istilah yang sangat tidak disarankan.
Leushenko
28

C (dengan GCC bawaan - juga tampaknya bekerja dengan dentang)

  • Tidak ada loop eksplisit
  • Tidak ada foto eksplisit
  • Tidak ada rekursi
  • Hanya cara kuno yang baik-baik saja dengan tumpukan (anak-anak, jangan coba ini di rumah tanpa pengawasan):
#include <stdio.h>

void *frameloop (void *ret_addr) {
    void **fp;
    void *my_ra = __builtin_return_address(0);

    if (ret_addr) {
        fp = __builtin_frame_address(0);
        if (*fp == my_ra) return (*fp = ret_addr);
        else fp++;
        if (*fp == my_ra) return (*fp = ret_addr);
        else fp++;
        if (*fp == my_ra) return (*fp = ret_addr);
        else fp++;
        if (*fp == my_ra) return (*fp = ret_addr);
        return NULL;
    } else {
        return (my_ra);
    }
}

int main (int argc, char **argv) {
    void *ret_addr;
    int i = 0;

    ret_addr = frameloop(NULL);
    printf("Hello World %d\n", i++);
    if (i < 10) {
        frameloop(ret_addr);
    }
}

Penjelasan:

  • main()panggilan pertama frameloop(NULL). Dalam hal ini gunakan __builtin_return_address()builtin untuk mendapatkan alamat pengirim main()yang frameloop()akan kembali ke. Kami mengembalikan alamat ini.
  • printf() untuk menunjukkan kita mengulang
  • sekarang kita panggil frameloop()dengan alamat pengirim untuk panggilan sebelumnya. Kami melihat melalui tumpukan untuk alamat pengirim saat ini, dan ketika kami menemukannya, kami mengganti alamat pengirim sebelumnya.
  • Kami kemudian kembali dari frameloop()panggilan ke-2 . Tetapi karena alamat pengirim diretas di atas, kami akhirnya kembali ke titik di main()mana panggilan pertama harus kembali. Jadi kita berakhir dalam satu lingkaran.

Pencarian untuk alamat pengirim di stack tentu saja akan lebih bersih sebagai sebuah loop, tapi saya membuka beberapa iterasi demi tidak mengulangi apa pun.

Keluaran:

$ CFLAGS=-g make frameloop
cc -g    frameloop.c   -o frameloop
$ ./frameloop 
Hello World 0
Hello World 1
Hello World 2
Hello World 3
Hello World 4
Hello World 5
Hello World 6
Hello World 7
Hello World 8
Hello World 9
$ 
Trauma Digital
sumber
2
bagus! Saya bertanya-tanya mengapa fungsi-fungsi itu bukan bagian dari spesifikasi C? ;-D
Brian Minton
4
@BrianMinton Sebenarnya hal serupa harus dapat dicapai dengan setjmp()/ longjmp(). Ini tidak dalam standar c, tetapi berada di perpustakaan standar . Aku merasa seperti menipiskan tumpukan secara manual hari ini ;-)
Digital Trauma
@BrianMinton Dugaan saya adalah karena ia ada dalam spesifikasi CPU, yang membuatnya tergantung pada perangkat keras. Dan agak berbahaya untuk digunakan ketika stackframe dibuat secara otomatis, saya tidak akan terkejut jika AV akan menangis tentang kode tersebut. Periksa ini atau ini untuk versi as86 x86.
PTwr
27

Haskell

Kode berikut ini tidak mengandung fungsi rekursif (bahkan secara tidak langsung), tidak ada pengulangan primitif dan tidak memanggil fungsi rekursifIO bawaan (hanya menggunakan keluaran dan pengikatan), namun kode ini mengulangi tindakan yang diberikan secara pasti:

data Strange a = C (Strange a -> a)

-- Extract a value out of 'Strange'
extract :: Strange a -> a
extract (x@(C x')) = x' x

-- The Y combinator, which allows to express arbitrary recursion
yc :: (a -> a) -> a
yc f =  let fxx = C (\x -> f (extract x))
        in extract fxx

main = yc (putStrLn "Hello world" >>)

Fungsi extracttidak memanggil apa pun, ycpanggilan adil extractdan mainpanggilan adil ycdan putStrLndan >>, yang tidak berulang.

Penjelasan: Caranya adalah pada tipe data rekursif Strange. Ini adalah tipe data rekursif yang mengkonsumsi sendiri, yang, seperti yang ditunjukkan dalam contoh, memungkinkan pengulangan sewenang-wenang. Pertama, kita dapat membangun extract x, yang pada dasarnya mengekspresikan penerapan diri x xdalam kalkulus lambda yang tidak diketik. Dan ini memungkinkan untuk membangun kombinator Y yang didefinisikan sebagai λf.(λx.f(xx))(λx.f(xx)).


Pembaruan: Seperti yang disarankan, saya memposting varian yang lebih dekat dengan definisi Y dalam kalkulus lambda yang tidak diketik:

data Strange a = C (Strange a -> a)

-- | Apply one term to another, removing the constructor.
(#) :: Strange a -> Strange a -> a
(C f) # x = f x
infixl 3 #

-- The Y combinator, which allows to express arbitrary recursion
yc :: (a -> a) -> a
yc f =  C (\x -> f (x # x)) # C (\x -> f (x # x))

main = yc (putStrLn "Hello world" >>)
Petr Pudlák
sumber
3
Struktur data rekursif bukan fungsi rekursif ... bagus.
ApproachingDarknessFish
6
yang ini dekat dengan hati saya menjadi seseorang yang tertarik pada pemrograman fungsional total. Anda baru saja menunjukkan cara membuat Y-combinator dengan tipe data berulang negatif. Inilah sebabnya mengapa bahasa total memerlukan jenis berulang terjadi di sebelah kanan panah dan mengapa pohon mawar dilarang. Yang bagus! Saya membuat akun di sini hanya untuk mengungguli ini!
Jake
Anda bisa menghapus letpengikatan dan mendefinisikan yc f = extract $ C $ f.extract, karena letpengikatan bisa dibilang fitur bahasa yang memungkinkan rekursi (klasik let x = x in x). Ini juga mengurangi beberapa karakter :)
Earth Engine
atau bahkanyc = extract . C . (.extract)
Earth Engine
@EarthEngine Benar, saya hanya ingin menjaga struktur lebih dekat dengan definisi asli Y.
Petr Pudlák
26

C ++

Berikut ini menampilkan hitungan mundur dari 10 ke "Blast off!" menggunakan metaprogramming template.

#include <iostream>

template<int N>
void countdown() {
    std::cout << "T minus " << N << std::endl;
    countdown<N-1>();
}

template<>
void countdown<0>() {
    std::cout << "Blast off!" << std::endl;
}

int main()
{
    countdown<10>();
    return 0;
}

Ini mungkin terlihat seperti contoh klasik rekursi, tetapi sebenarnya tidak, setidaknya secara teknis, tergantung pada definisi Anda. Kompiler akan menghasilkan sepuluh fungsi berbeda . countdown<10>mencetak "T minus 10" dan kemudian memanggil countdown<9>, dan seterusnya ke countdown<0>, yang mencetak "Lepaskan!" dan kemudian kembali. Rekursi terjadi ketika Anda mengkompilasi kode, tetapi executable tidak mengandung struktur pengulangan.

Dalam C ++ 11 orang dapat mencapai efek yang sama menggunakan constexprkata kunci, seperti fungsi faktorial ini. (Ini tidak mungkin untuk menerapkan contoh hitung mundur dengan cara ini, karena constexprfungsi tidak dapat memiliki efek samping, tapi saya pikir itu mungkin terjadi di C ++ 14 mendatang.)

constexpr int factorial(int n)
{
    return n <= 1 ? 1 : (n * factorial(n-1));
}

Sekali lagi ini benar-benar tampak seperti rekursi, tetapi kompiler akan berkembang factorial(10)menjadi 10*9*8*7*6*5*4*3*2*1, dan kemudian mungkin menggantinya dengan nilai konstan 3628800, sehingga executable tidak akan berisi kode perulangan atau rekursif.

Nathaniel
sumber
4
Yang kedua ini benar-benar rekursi murni dan sederhana, bukan metaprogramming. Pertama karena kompiler akan (dalam kasus umum) memancarkan fungsi tubuh reguler untuk Anda gunakan dengan argumen tidak konstan; dan kedua karena ketika ia melakukan operasi waktu kompilasi, ia tidak melakukan hal-hal "ekspansi" gaya template, ia menjalankan evaluasi di tempat standar - sama dengan yang runtime - untuk menghasilkan 3628800langsung tanpa bentuk peralihan.
Leushenko
@ Leushenko ya aku tahu. Tapi sekali lagi contoh contoh template melakukan hal yang sama - menggunakan fungsi rekursif dalam bahasa Turing-lengkap pada waktu kompilasi - satu-satunya perbedaan adalah bahwa constexpr yang menggunakan bahasa yang jauh lebih mirip dengan C ++. Seperti semua jawaban yang satu ini membengkokkan aturan, dan saya hanya jujur ​​tentang hal itu. constexprsecara khusus dirancang untuk membuat (beberapa aspek) metaprogramming template menjadi usang, jadi sepertinya layak disebutkan dalam posting pada subjek.
Nathaniel
1
1: &countdown<N-1> != &countdown<N>.
Thomas Eding
21

Jawa

Mari bermain dengan pemuat kelas Java dan atur sebagai induknya sendiri:

import java.lang.reflect.Field;

public class Loop {
    public static void main(String[] args) throws Exception {
        System.out.println("Let's loop");
        Field field = ClassLoader.class.getDeclaredField("parent");
        field.setAccessible(true);
        field.set(Loop.class.getClassLoader(), Loop.class.getClassLoader());

    }
}

Loop ini sebenarnya sangat kuat sehingga Anda harus menggunakan kill -9untuk menghentikannya :-)

Ini menggunakan 100,1% dari CPU Mac saya.

100,1% dari CPU

Anda dapat mencoba untuk memindahkan System.outdi akhir fungsi utama untuk bereksperimen perilaku lucu alternatif.

Arnaud
sumber
lol. mendapatkan java terjebak dalam dirinya sendiri :)
masterX244
Suka hack pemuatan rekursif JVM.
Isiah Meadows
20

CSharp

Satu lagi yang sama jahatnya ::

public class P{

    class A<B>{
        public static int C<T>(){
            System.Console.WriteLine(typeof(T));
            return C<A<T>>();
        }
    }
    public static void Main(){
        A<P>.C<int>();
    }
}

Ini bukan rekursi ... ini adalah reifikasi templat kode. Meskipun tampaknya kami memanggil metode yang sama, runtime terus-menerus membuat metode baru. Kami menggunakan tipe parameter int, karena ini benar-benar memaksanya untuk membuat seluruh tipe baru dan setiap instance dari metode harus membuang metode baru. Tidak dapat memberi kode berbagi di sini. Akhirnya, kami membunuh tumpukan panggilan karena menunggu kembalinya int yang kami janjikan tetapi tidak pernah dikirimkan. Dengan cara yang sama, kami terus menulis jenis yang kami buat agar tetap menarik. Pada dasarnya setiap C yang kita panggil adalah metode baru yang benar-benar baru yang hanya memiliki tubuh yang sama. Ini tidak benar-benar mungkin dalam bahasa seperti C ++ atau D yang melakukan templat mereka pada waktu kompilasi. Karena, C # JIT sangat malas, itu hanya menciptakan hal-hal ini pada saat-saat terakhir. Jadi,

Michael B
sumber
14

Redcode 94 (Perang Inti)

MOV 0, 1

Salinan instruksi di alamat nol ke alamat satu. Karena dalam Core War semua alamat relatif terhadap alamat PC saat ini dan memodul ukuran inti, ini adalah loop tak terbatas dalam satu instruksi, non-lompat.

Program ini (prajurit) disebut " Imp " dan pertama kali diterbitkan oleh AK Dewdney.

wberry
sumber
3
Pas akan berbaris, siapkan gerbang Anda, siapkan mereka atau Anda akan hancur.
seequ
Siapkan Anda SPL 0, 0; MOV 1, -2memang.
wberry
Bagus, saya berharap ini belum diposting. +1
mbomb007
14

Anak panah

Saya kira ini akan menjadi cara klasik untuk melakukan rekursi tanpa fungsi rekursif yang sebenarnya. Tidak ada fungsi di bawah ini mengacu pada namanya sendiri, secara langsung atau tidak langsung.

(Cobalah di dartpad.dartlang.org )

// Strict fixpoint operator.
fix(f) => ((x)=>f(x(x))) ((x)=>(v)=>f(x(x))(v));
// Repeat action while it returns true.
void repeat(action) { fix((rep1) => (b) { if (b()) rep1(b); })(action); }

main() {
  int x = 0;
  repeat(() {  
    print(++x);
    return x < 10;
  });
}
Tuan
sumber
6
Penggabung Y?
aditsu
5
Secara teknis, saya kira itu adalah kombinasi Z karena itu untuk bahasa yang ketat. Penggabung Y membutuhkan bahasa yang malas untuk menghindari pembukaan yang tidak terbatas. Satu-satunya perbedaan adalah bahwa bagian terakhirnya adalah eta-diperluas.
lrn
12

JS

Tidak sangat asli tetapi kecil. 20 karakter.

setInterval(alert,1)
xem
sumber
Anda benar-benar dapat menghapus ,1dan itu masih akan berfungsi,
Derek 朕 會 功夫
@Derek 朕 會 功夫 jika saya melakukan itu, saya hanya mendapatkan satu peringatan di Firefox
xem
1
Di chrome berfungsi tanpa parameter terakhir. Kode harus dihitung valid jika bekerja di setidaknya satu lingkungan.
Derek 朕 會 功夫
3
@Derek 朕 會 功夫setIntervalbukan merupakan pernyataan; itu hanya sebuah fungsi. Ini digunakan di dalam pernyataan ekspresi, dan jika kita tidak bisa menggunakan pernyataan ekspresi, maka saya bahkan tidak tahu lagi.
Tertarik
1
@Cory - Ya saya kira itu sah saja!
Derek 朕 會 功夫
12

Sinyal dalam C

#include <stdio.h>
#include <signal.h>

int main(void) {
    signal(SIGSEGV, main);
    *(int*)printf("Hello, world!\n") = 0;
    return 0;
}

Perilaku program ini jelas sangat tidak terdefinisi, tetapi hari ini, di komputer saya, ia terus mencetak "Halo, dunia!".

Thomas Padron-McCarthy
sumber
11

Emacs Lisp

Ini adalah waktu yang tepat untuk memamerkan desain Lisp yang kuat di mana "kode adalah data dan data adalah kode". Memang, contoh-contoh ini sangat tidak efisien dan ini tidak boleh digunakan dalam konteks nyata.

Makro menghasilkan kode yang merupakan versi tidak terbaca dari loop yang seharusnya dan kode yang dihasilkan adalah apa yang dievaluasi saat runtime.

repeat-it: memungkinkan Anda untuk mengulang N kali

(defmacro repeat-it (n &rest body)
  "Evaluate BODY N number of times.
Returns the result of the last evaluation of the last expression in BODY."
  (declare (indent defun))
  (cons 'progn (make-list n (cons 'progn body))))

tes pengulangan:

;; repeat-it test
(progn
  (setq foobar 1)

  (repeat-it 10
    (setq foobar (1+ foobar)))

  ;; assert that we incremented foobar n times
  (assert (= foobar 11)))

ulangi dengan indeks:

Makro ini seperti repeat-ittetapi sebenarnya berfungsi seperti makro perulangan umum, do-timesini memungkinkan Anda menentukan simbol yang akan terikat pada indeks lingkaran. Ini menggunakan simbol waktu ekspansi untuk memastikan bahwa variabel indeks diatur dengan benar di awal setiap loop terlepas dari apakah Anda memodifikasi nilainya selama tubuh loop.

(defmacro repeat-it-with-index (var-and-n &rest body)
  "Evaluate BODY N number of times with VAR bound to successive integers from 0 inclusive to n exclusive..
VAR-AND-N should be in the form (VAR N).
Returns the result of the last evaluation of the last expression in BODY."
  (declare (indent defun))
  (let ((fallback-sym (make-symbol "fallback")))
    `(let ((,(first var-and-n) 0)
           (,fallback-sym 0))
       ,(cons 'progn
              (make-list (second var-and-n)
                         `(progn
                            (setq ,(first var-and-n) ,fallback-sym)
                            ,@body
                            (incf ,fallback-sym)))))))

tes pengulangan-dengan-indeks:

Tes ini menunjukkan bahwa:

  1. Tubuh mengevaluasi N kali

  2. variabel indeks selalu diatur dengan benar di awal setiap iterasi

  3. mengubah nilai simbol bernama "fallback" tidak akan mengacaukan indeks

;; repeat-it-with-index test
(progn
  ;; first expected index is 0
  (setq expected-index 0)

  ;; start repeating
  (repeat-it-with-index (index 50)
    ;; change the value of a  'fallback' symbol
    (setq fallback (random 10000))
    ;; assert that index is set correctly, and that the changes to
    ;; fallback has no affect on its value
    (assert (= index expected-index))
    ;; change the value of index
    (setq index (+ 100 (random 1000)))
    ;; assert that it has changed
    (assert (not (= index expected-index)))
    ;; increment the expected value
    (incf expected-index))

  ;; assert that the final expected value is n
  (assert (= expected-index 50)))
Jordon Biondo
sumber
11

Kalkulus lambda yang tidak diketik

λf.(λx.f (x x)) (λx.f (x x))
Arthur B
sumber
3
Saya tidak yakin apakah ini dianggap rekursi atau tidak, apalagi dengan menjadi dasar teori fundamental untuk itu ... +1.
lembut
@ Fluffy Ini bukan rekursif itu sendiri, tidak ada fungsi yang menyebut diri mereka sendiri (terutama karena fungsi tidak bernama).
haskeller bangga
IMHO, kalkulus lambda adalah model perhitungan dan bukan bahasa pemrograman (yaitu tanpa model mesin beton, kami tidak dapat menganggap kalkulus lambda sebagai PL).
Ta Thanh Dinh
Anda benar-benar dapat membangun mesin yang menginterpretasikan kalkulus lambda. Dan sintaks dapat digunakan sebagai bahasa pemrograman. Lihat misalnya github.com/MaiaVictor/caramel
Arthur B
10

Haskell, 24 karakter

sequence_ (repeat (print "abc"))

atau dalam bentuk kental, dengan 24 karakter

sequence_$repeat$print"" 

(walaupun teksnya diubah, ini masih akan berulang - ini akan mencetak dua tanda kutip dan baris baru tanpa batas)

PENJELASAN: mencetak "abc" pada dasarnya adalah tindakan i / o yang hanya mencetak "abc".
repeat adalah fungsi yang mengambil nilai x dan mengembalikan daftar tak terbatas yang hanya terbuat dari x.
sequence_ adalah fungsi yang mengambil daftar tindakan i / o dan mengembalikan tindakan i / o yang melakukan semua tindakan secara berurutan.

jadi, pada dasarnya, program ini membuat daftar perintah "abc" cetak yang tak terbatas, dan berulang kali mengeksekusinya. tanpa loop atau rekursi.

haskeller bangga
sumber
4
Saya pada dasarnya akan memposting jawaban yang sama di Clojure, tetapi saya pikir repeatakan a programming language statement which allows code to be repeatedly executed.
seequ
3
fix(print"">>), ini juga tidak melibatkan fungsi pengulangan yang secara eksplisit disebut.
mniip
1
@TheRare Saya tidak tahu bagaimana penutupannya, tetapi di Haskell repeat bukan "pernyataan bahasa pemrograman yang memungkinkan kode dieksekusi berulang kali" - ini adalah fungsi yang menghasilkan daftar tak terbatas. itu adalah sebuah loop seperti "int [] arr = {x, x, x};" adalah sebuah loop.
haskeller bangga
1
ya, tetapi sesuatu harus diimplementasikan menggunakan rekursi, karena tanpanya itu pada dasarnya tidak mungkin
bangga haskeller
3
Sebenarnya, setiap fungsi yang ada dalam kode ini didefinisikan menggunakan rekursi - bahkan cetak
bangga haskeller
10

ASM (x86 + I / O untuk Linux)

Tidak peduli berapa banyak bahasa tingkat rendah Anda akan berjuang, itu masih akan menjadi manipulasi pointer instruksi tersembunyi. Pada akhirnya itu akan menjadi semacam "goto" (jmp), kecuali jika Anda cukup bosan untuk membuka gulungan di runtime.

Anda dapat menguji kode pada Ideone

Anda juga dapat melihat versi yang lebih baik dari ide ini dalam kode DOS Matteo Italia .

Itu dimulai dengan string 0..9 dan menggantinya dengan A..J, tidak ada lompatan langsung yang digunakan (jadi katakanlah tidak ada "goto" terjadi), tidak ada pengulangan juga.

Kode mungkin bisa lebih kecil dengan beberapa penyalahgunaan perhitungan alamat, tetapi mengerjakan kompiler online itu menyusahkan jadi saya akan membiarkannya apa adanya.

Bagian inti:

mov dl, 'A' ; I refuse to explain this line!
mov ebx, msg ; output array (string)

call rawr   ; lets put address of "rawr" line on stack
rawr: pop eax ; and to variable with it! In same time we are breaking "ret"

add eax, 4 ; pop eax takes 4 bytes of memory, so for sake of stack lets skip it
mov [ebx], dl ; write letter
inc dl ; and proceed to next 
inc ebx
cmp dl, 'J' ; if we are done, simulate return/break by leaving this dangerous area
jg print

push eax ; and now lets abuse "ret" by making "call" by hand
ret

Seluruh kode

section     .text
global      _start                              

_start:

;<core>
mov dl, 'A'
mov ebx, msg

call rawr
rawr: pop eax

add eax, 4
mov [ebx], dl
inc dl
inc ebx
cmp dl, 'J'
jg print

push eax
ret
;</core>

; just some Console.Write()
print:
    mov     edx,len
    mov     ecx,msg
    mov     ebx,1
    mov     eax,4
    int     0x80

    mov     eax,1
    xor     ebx, ebx
    int     0x80

section     .data

msg     db  '0123456789',0xa
len     equ $ - msg
PTWR
sumber
Saya akan menyebut ini sebagai dup codegolf.stackexchange.com/a/34298/11259 , tetapi saya melihat ini adalah jawaban sebelumnya. +1
Trauma Digital
@DigitalTrauma oh, saya melihat seseorang membuat versi ide saya yang bagus - trik lama, tetapi di era kode yang dikelola orang cenderung lupa bagaimana segala sesuatunya bekerja. (Saya tidak suka bermain golf, terlalu sering direduksi menjadi "lihat ibu! Saya bisa mewujudkannya dengan menekan satu tombol!")
PTwr
9

C Preprocessor

Sedikit "teknik" yang saya buat selama tantangan kebingungan. Tidak ada rekursi fungsi, tetapi ada ... rekursi file?

noloop.c:

#if __INCLUDE_LEVEL__ == 0
int main() 
{
    puts("There is no loop...");
#endif
#if __INCLUDE_LEVEL__ <= 16
    puts(".. but Im in ur loop!");
    #include "noloop.c"
#else
    return 0;
}
#endif

Saya menulis / menguji ini menggunakan gcc. Jelas kompiler Anda perlu mendukung __INCLUDE_LEVEL__makro (atau alternatifnya __COUNTER__makro dengan beberapa penyesuaian) agar dapat dikompilasi. Seharusnya cukup jelas bagaimana ini bekerja, tetapi untuk bersenang-senang, jalankan preprocessor tanpa mengkompilasi kode (gunakan -Ebendera dengan gcc).

ApproachingDarknessFish
sumber
8

PHP

Inilah satu dengan PHP. Loop dengan memasukkan file yang sama hingga penghitung mencapai $ maks:

<?php
if (!isset($i))
    $i = 0;        // Initialize $i with 0
$max = 10;         // Target value

// Loop body here
echo "Iteration $i <br>\n";

$i++;               // Increase $i by one on every iteration

if ($i == $max)
    die('done');    // When $i reaches $max, end the script
include(__FILE__);  // Proceed with the loop
?>

Sama seperti for-loop:

<?php
for ($i = 0; $i < 10; $i++) {
    echo "Iteration $i <br>\n";
}
die('done');
?>
Pichan
sumber
Sial, ini juga dianggap rekursi, bukan?
Pichan
Jangan berpikir begitu - kesamaannya muncul di contoh @ Nathaniel: preprocessor akan menyertakan file-file ini yang kemudian dievaluasi secara bersamaan.
eithed
@Pichan saya akan mengatakan itu lebih dari loop terbuka, karena Anda berakhir dengan salinan kode di memori.
PTwr
Saya baru saja melihat pertanyaan hari ini dan muncul dengan kode yang hampir sama. Terlambat untukku!
TecBrat
Apakah header("Location: .?x=".$_GET['x']+1);dihitung sebagai rekursi?
Charlie
8

Python

Kode berikut tidak mengandung fungsi rekursif (langsung atau tidak langsung), tidak ada perulangan primitif dan tidak memanggil fungsi bawaan apa pun (kecuali print):

def z(f):
    g = lambda x: lambda w: f(lambda v: (x(x))(v), w)
    return g(g)

if __name__ == "__main__":
    def msg(rec, n):
        if (n > 0):
            print "Hello world!"
            rec(n - 1)
    z(msg)(7)

Cetakan "Halo dunia!" beberapa kali.

Penjelasan: Fungsi zmengimplementasikan combinator titik tetap Z yang ketat , yang (walaupun tidak didefinisikan secara rekursif) memungkinkan untuk mengekspresikan algoritma rekursif apa pun.

Petr Pudlák
sumber
Saya akan menyebutnya gsangat tidak langsung bersifat rekursif.
seequ
@TheRare Mengapa? Apa argumen Anda? Apa yang gdisebut panggilan itu glagi? Tentu saja triknya adalah aplikasi diri g(g), tetapi tidak ada rekursi yang terlibat. Apakah Anda memang menyebut gsecara tidak langsung rekursif jika Anda belum melihat g(g)? Ini adalah cara standar bagaimana melakukannya dalam bahasa yang tidak memungkinkan definisi rekursif, seperti kalkulus lambda.
Petr Pudlák
Anda memberi gsebagai argumen xdan kemudian menelepon x(x).
seequ
2
@TheRare Fungsi (atau serangkaian fungsi) tidak rekursif atau non-rekursif dengan cara penggunaannya, ini ditentukan hanya dengan definisinya.
Petr Pudlák
1
semua jawaban curang dalam satu atau lain cara: selalu ada rekursi atau loop di suatu tempat , jika tidak dalam jawaban, maka dalam kode jawabannya dipanggil. Saya suka cara ini menipu.
Wayne Conrad
8

kode mesin z80

Dalam lingkungan di mana Anda dapat mengeksekusi di setiap alamat dan memetakan ROM di mana-mana, peta 64kb ROM diisi dengan nol ke seluruh ruang alamat.

Apa yang dilakukannya: tidak ada. Berkali-kali.

Cara kerjanya: prosesor akan mulai mengeksekusi, byte 00adalah nopinstruksi, jadi itu hanya akan melanjutkan, mencapai alamat $ffff, membungkus sekitar $0000, dan terus mengeksekusi nopsampai Anda meresetnya.

Untuk membuatnya sedikit lebih menarik, isi memori dengan nilai lain (hati-hati untuk menghindari instruksi aliran kontrol).

Harold
sumber
Anda bisa mengisi memori dengan nol, dan menempatkan program nyata di sana di suatu tempat.
seequ
Jadi Anda bisa memasukkan program 64k, tanpa bercabang apa pun, dan itu hanya akan berulang kali dijalankan?
Bill Woodger
@BillWoodger Anda bisa, terutama jika Anda tidak memiliki interupsi pada platform (atau tidak ada yang diaktifkan)
harold
Agak menyenangkan :-)
Bill Woodger
8

Perl-regex

(q x x x 10) =~ /(?{ print "hello\n" })(?!)/;

demo

atau coba sebagai:

perl -e '(q x x x 10) =~ /(?{ print "hello\n" })(?!)/;'

Yang (?!)tidak pernah cocok. Jadi mesin regex mencoba untuk mencocokkan setiap posisi lebar nol dalam string yang cocok.

Yang (q x x x 10)sama (" " x 10)- ulangi spacesepuluh kali.

Sunting: mengubah "karakter" ke posisi nol lebar menjadi lebih tepat agar lebih mudah dipahami. Lihat jawaban untuk pertanyaan stackoverflow ini .

jm666
sumber
6

T-SQL -12

print 1
GO 9

Sebenarnya lebih merupakan kekhasan dari Sql Server Management Studio. GO adalah pemisah skrip dan bukan bagian dari bahasa T-SQL. Jika Anda menentukan GO diikuti oleh angka itu akan mengeksekusi blok yang berkali-kali.

Michael B
sumber
1
Saya menggunakan T-SQL hampir setiap hari dan tidak tahu Anda bisa melakukan ini dengan GO. +1
CailinP
Secara teknis, itu bukan T-SQL. GOsebenarnya adalah arahan SSMS, itulah sebabnya Anda tidak bisa memasukkannya ke objek skrip T-SQL, seperti misalnya prosedur tersimpan.
RBarryYoung
Ya, saya menambahkan itu di komentar spoiler saya. Saya pikir menggunakan sqlcmd akan terlalu banyak kecurangan.
Michael B
6

C #

Mencetak semua bilangan bulat dari uint.MaxValue ke 0.

   class Program
   {
      public static void Main()
      {
          uint max = uint.MaxValue;
          SuperWriteLine(ref max);
          Console.WriteLine(0);
      }

      static void SuperWriteLine(ref uint num)
      {
          if ((num & (1 << 31)) > 0) { WriteLine32(ref num); }
          if ((num & (1 << 30)) > 0) { WriteLine31(ref num); }
          if ((num & (1 << 29)) > 0) { WriteLine30(ref num); }
          if ((num & (1 << 28)) > 0) { WriteLine29(ref num); }
          if ((num & (1 << 27)) > 0) { WriteLine28(ref num); }
          if ((num & (1 << 26)) > 0) { WriteLine27(ref num); }
          if ((num & (1 << 25)) > 0) { WriteLine26(ref num); }
          if ((num & (1 << 24)) > 0) { WriteLine25(ref num); }
          if ((num & (1 << 23)) > 0) { WriteLine24(ref num); }
          if ((num & (1 << 22)) > 0) { WriteLine23(ref num); }
          if ((num & (1 << 21)) > 0) { WriteLine22(ref num); }
          if ((num & (1 << 20)) > 0) { WriteLine21(ref num); }
          if ((num & (1 << 19)) > 0) { WriteLine20(ref num); }
          if ((num & (1 << 18)) > 0) { WriteLine19(ref num); }
          if ((num & (1 << 17)) > 0) { WriteLine18(ref num); }
          if ((num & (1 << 16)) > 0) { WriteLine17(ref num); }
          if ((num & (1 << 15)) > 0) { WriteLine16(ref num); }
          if ((num & (1 << 14)) > 0) { WriteLine15(ref num); }
          if ((num & (1 << 13)) > 0) { WriteLine14(ref num); }
          if ((num & (1 << 12)) > 0) { WriteLine13(ref num); }
          if ((num & (1 << 11)) > 0) { WriteLine12(ref num); }
          if ((num & (1 << 10)) > 0) { WriteLine11(ref num); }
          if ((num & (1 << 9)) > 0) { WriteLine10(ref num); }
          if ((num & (1 << 8)) > 0) { WriteLine09(ref num); }
          if ((num & (1 << 7)) > 0) { WriteLine08(ref num); }
          if ((num & (1 << 6)) > 0) { WriteLine07(ref num); }
          if ((num & (1 << 5)) > 0) { WriteLine06(ref num); }
          if ((num & (1 << 4)) > 0) { WriteLine05(ref num); }
          if ((num & (1 << 3)) > 0) { WriteLine04(ref num); }
          if ((num & (1 << 2)) > 0) { WriteLine03(ref num); }
          if ((num & (1 <<  1)) > 0) { WriteLine02(ref num); }
          if ((num & (1 <<  0)) > 0) { WriteLine01(ref num); }
      }

      private static void WriteLine32(ref uint num) { WriteLine31(ref num); WriteLine31(ref num); }
      private static void WriteLine31(ref uint num) { WriteLine30(ref num); WriteLine30(ref num); }
      private static void WriteLine30(ref uint num) { WriteLine29(ref num); WriteLine29(ref num); }
      private static void WriteLine29(ref uint num) { WriteLine28(ref num); WriteLine28(ref num); }
      private static void WriteLine28(ref uint num) { WriteLine27(ref num); WriteLine27(ref num); }
      private static void WriteLine27(ref uint num) { WriteLine26(ref num); WriteLine26(ref num); }
      private static void WriteLine26(ref uint num) { WriteLine25(ref num); WriteLine25(ref num); }
      private static void WriteLine25(ref uint num) { WriteLine24(ref num); WriteLine24(ref num); }
      private static void WriteLine24(ref uint num) { WriteLine23(ref num); WriteLine23(ref num); }
      private static void WriteLine23(ref uint num) { WriteLine22(ref num); WriteLine22(ref num); }
      private static void WriteLine22(ref uint num) { WriteLine21(ref num); WriteLine21(ref num); }
      private static void WriteLine21(ref uint num) { WriteLine20(ref num); WriteLine20(ref num); }
      private static void WriteLine20(ref uint num) { WriteLine19(ref num); WriteLine19(ref num); }
      private static void WriteLine19(ref uint num) { WriteLine18(ref num); WriteLine18(ref num); }
      private static void WriteLine18(ref uint num) { WriteLine17(ref num); WriteLine17(ref num); }
      private static void WriteLine17(ref uint num) { WriteLine16(ref num); WriteLine16(ref num); }
      private static void WriteLine16(ref uint num) { WriteLine15(ref num); WriteLine15(ref num); }
      private static void WriteLine15(ref uint num) { WriteLine14(ref num); WriteLine14(ref num); }
      private static void WriteLine14(ref uint num) { WriteLine13(ref num); WriteLine13(ref num); }
      private static void WriteLine13(ref uint num) { WriteLine12(ref num); WriteLine12(ref num); }
      private static void WriteLine12(ref uint num) { WriteLine11(ref num); WriteLine11(ref num); }
      private static void WriteLine11(ref uint num) { WriteLine10(ref num); WriteLine10(ref num); }
      private static void WriteLine10(ref uint num) { WriteLine09(ref num); WriteLine09(ref num); }
      private static void WriteLine09(ref uint num) { WriteLine08(ref num); WriteLine08(ref num); }
      private static void WriteLine08(ref uint num) { WriteLine07(ref num); WriteLine07(ref num); }
      private static void WriteLine07(ref uint num) { WriteLine06(ref num); WriteLine06(ref num); }
      private static void WriteLine06(ref uint num) { WriteLine05(ref num); WriteLine05(ref num); }
      private static void WriteLine05(ref uint num) { WriteLine04(ref num); WriteLine04(ref num); }
      private static void WriteLine04(ref uint num) { WriteLine03(ref num); WriteLine03(ref num); }
      private static void WriteLine03(ref uint num) { WriteLine02(ref num); WriteLine02(ref num); }
      private static void WriteLine02(ref uint num) { WriteLine01(ref num); WriteLine01(ref num); }
      private static void WriteLine01(ref uint num) { Console.WriteLine(num--); }
   }
LVBen
sumber
1
Saya tidak benar-benar tahu apakah ini penting. Anda secara eksplisit memanggil waktu WriteLine01 Int.MaxValue. Itu hanya meledak di belakang sejumlah besar callstack.
Michael B
Bagaimana itu tidak dihitung? Tidak ada loop dan tidak ada rekursi.
LVBen
1
Juga, tumpukan panggilan tidak berada di dekat masif kecuali jika Anda menganggap 32 panggilan tinggi sebagai masif.
LVBen
1
Mengapa hanya 32 kali, bukannya 4294967296 kali?
LVBen
4
@ ja72 Jika saya pernah bekerja pada proyek open source di mana saya tidak dapat menggunakan loop atau rekursi, maka saya benar-benar akan berkontribusi kode seperti ini!
LVBen
6

JS (di browser)

Bagaimana dengan ini?

document.write(new Date());
location = location;

Mencetak waktu saat ini dan memuat kembali halaman.

Pichan
sumber
Oh sial. Saya baru saja mengirim jawaban dengan konsep dasar yang sama. Saya telah memindai halaman untuk "JavaScript" atau apa pun yang menunjukkan tag HTML. Saya kira saya mungkin meninggalkan jawaban saya, hanya karena ini menangani kasus sudut di mana lokasi berisi "#". Pokoknya, +1.
Tertarik
Di Firefox 30:[Exception... "The operation is insecure." code: "18" nsresult: "0x80530012 (SecurityError)" location: "<unknown>"]
Alex Reynolds
@AlexReynolds Huh, aneh. Milik saya bekerja dengan baik pada FF 30.
Pichan
Saya hanya menyalin dan menempelkan kode Anda seperti yang tertulis. Itu tidak bekerja. Mungkin Anda memiliki beberapa preferensi keamanan khusus yang diaktifkan untuk membuat ini berfungsi?
Alex Reynolds
@AlexReynolds Tidak, tidak pernah mengubah pengaturan keamanan apa pun. Dan itu berfungsi di Chrome juga.
Pichan