Mẹo tạo polyglots


48

Một là một chương trình có thể được chạy trong 2 hoặc nhiều ngôn ngữ lập trình khác nhau.

Bạn có mẹo chung nào để tạo các đa âm hoặc chọn các ngôn ngữ dễ viết các đa âm cho một tác vụ cụ thể?

Xin vui lòng gửi các mẹo có thể được áp dụng trong hầu hết các tình huống. Tức là họ không nên làm việc chỉ trong các đa ngôn ngữ của hai ngôn ngữ cụ thể. (Bạn chỉ có thể đăng câu trả lời cho câu hỏi đa âm nếu bạn có một mẹo quá cụ thể.) Nhưng bạn có thể giới thiệu các tính năng của ngôn ngữ giúp dễ dàng làm việc với nhiều ngôn ngữ hoặc dễ dàng được thêm vào bất kỳ đa ngôn ngữ hiện có nào.

Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời. Và hãy thoải mái đề nghị chỉnh sửa nếu một mẹo dành riêng cho ngôn ngữ cũng áp dụng cho ngôn ngữ khác.

Câu trả lời:


25

Khai thác các ký hiệu nhận xét

Một cách đơn giản để tạo một polyglot hai ngôn ngữ là mã được chia thành hai phần như sau:

  1. Phần đầu tiên thực hiện công việc thực tế trong ngôn ngữ A, vô hại trong ngôn ngữ B (không có lỗi) và kết thúc bằng ngôn ngữ - Một biểu tượng nhận xét, ẩn phần thứ hai với ngôn ngữ A.
  2. Phần thứ hai thực hiện công việc thực tế trong ngôn ngữ B.

Do vậy

  • Ngôn ngữ A nhìn thấy phần đầu tiên, thực hiện công việc, và sau đó là một nhận xét.
  • Ngôn ngữ B thấy một phần đầu tiên vô dụng và sau đó là phần thứ hai, thực hiện công việc.

Phần khó khăn duy nhất ở đây là tìm một tập hợp các câu lệnh (phần đầu tiên) thực hiện công việc bằng ngôn ngữ A trong khi không đưa ra lỗi về ngôn ngữ B. Một số gợi ý cho việc này:

  • Hầu hết các ngôn ngữ dựa trên ngăn xếp cho phép chỉ hiển thị phần trên cùng của ngăn xếp ở cuối chương trình (đôi khi điều này thậm chí là mặc định, như trong 05AB1E).
  • Một số ngôn ngữ bỏ qua các câu lệnh không xác định (ví dụ: Golfscript).

Một ví dụ đơn giản sử dụng các hướng dẫn này có thể được tìm thấy ở đây . Ngôn ngữ A và B lần lượt là MATL05AB1E .


24

Sử dụng ngôn ngữ hai chiều

Không giống như các ngôn ngữ một chiều, thường phân tích toàn bộ mã nguồn và sẽ tạo ra lỗi cú pháp hoặc hiệu ứng thời gian chạy không mong muốn đối với những thứ chúng không hiểu (do đó buộc bạn phải ẩn mã của các ngôn ngữ khác khỏi chúng), các ngôn ngữ hai chiều chỉ có xu hướng mã phân tích cú pháp trong đường dẫn thực thi, nghĩa là toàn bộ phần còn lại của chương trình bị bỏ qua. Ngoài ra còn có nhiều chỗ để phân chia các đường thực thi cách xa nhau theo hai chiều; bạn có thể gửi con trỏ lệnh quay theo hướng bất thường, như xuống hoặc thậm chí sang trái (quấn vòng sang phía bên phải của chương trình), để nhanh chóng đưa nó ra khỏi đường đi của bạn. Các kỹ thuật hữu ích trong các ngôn ngữ một chiều cũng khái quát thành các ngôn ngữ hai chiều (ví dụ: bạn có thể bỏ qua mã với;; trong Befunge-98, ngoài việc chỉ gửi IP theo một hướng kỳ lạ), làm cho điều này chủ yếu chỉ là một lợi ích nghiêm ngặt so với giải pháp một chiều.

Như một phần thưởng, một số ngôn ngữ hai chiều có một điểm vào khác ngoài góc trên bên trái của chương trình, nghĩa là bạn không cần phải nỗ lực để tách chúng ra khỏi các ngôn ngữ khác; họ sẽ tách ra khỏi nhóm một cách tự nhiên.


20

Biết Trues và Falses của bạn

Mỗi ngôn ngữ nhìn "đúng" và "sai" theo một cách hơi khác nhau. Nếu chúng có cú pháp tương tự, bạn có thể khai thác điều này bằng cách thêm một quyết định rằng các ngôn ngữ sẽ xử lý khác nhau.

Một ví dụ từ luồng Trick hoặc Treat sử dụng '', một chuỗi rỗng. Trong Lua, điều này đánh giá là trung thực, nhưng giả mạo trong Python, vì vậy như sau:

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

.. sẽ in một chuỗi khác nhau trong mỗi ngôn ngữ.

Tất cả chỉ cần tìm một giá trị như thế này. Ví dụ: bạn có thể sử dụng '0', đánh giá falsetrong PHP nhưng truebằng Python.


17

Blockquote trong ít nhất một ngôn ngữ

Đây là một ví dụ hoạt động cả trong Python và C ++

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

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

Luis Mendo đã đưa ra những gì tôi nghĩ là giải pháp đơn giản nhất, đó là sử dụng các bình luận.

Bạn tìm kiếm một ngôn ngữ có chặn nhận xét và ngôn ngữ khác trong đó cú pháp thông thường trong lần đầu tiên là cú pháp nhận xét trong lần thứ hai.

Thậm chí dễ dàng hơn là hai ngôn ngữ với các kiểu nhận xét khối khác nhau có thể thay thế cú pháp chính xác, nhưng tôi không thể bận tâm kiểm tra.

Hãy xem thử trong Python 3.5C ++


2
Dòng đầu tiên không nên có dấu chấm phẩy.

Thật. Điểm tốt
dexgecko

15

Phân chia và chinh phục

Khi bạn viết một đa âm bằng một số lượng lớn ngôn ngữ, bạn sẽ không nhất thiết có thể tách tất cả các luồng điều khiển của ngôn ngữ khỏi nhau ngay lập tức. Do đó, bạn sẽ cần "đa âm thực sự" một số ngôn ngữ trong một khoảng thời gian, cho phép cùng một mã chạy trong mỗi ngôn ngữ. Có hai quy tắc chính cần ghi nhớ khi bạn thực hiện điều này:

  • Luồng điều khiển trong bất kỳ hai ngôn ngữ nên rất giống nhau hoặc rất khác nhau . Cố gắng xử lý một số lượng lớn các luồng điều khiển xen kẽ là một công thức để bị lẫn lộn và làm cho chương trình của bạn khó sửa đổi. Thay vào đó, bạn nên giới hạn số lượng công việc bạn phải làm bằng cách đảm bảo rằng tất cả các chương trình ở cùng một nơi đều có cùng lý do và có thể vui vẻ chạy song song miễn là bạn cần. Trong khi đó, nếu một ngôn ngữ rất khác với ngôn ngữ khác, bạn muốn việc thực thi ngôn ngữ đó chuyển đến một vị trí rất khác càng sớm càng tốt, do đó bạn không phải cố gắng làm cho mã của mình tuân theo hai mô hình cú pháp khác nhau cùng một lúc.

  • Tìm kiếm cơ hội để phân chia một ngôn ngữ hoặc một nhóm các ngôn ngữ tương tự, cách xa nhau. Làm việc từ các nhóm lớn hơn xuống các nhóm nhỏ hơn. Khi bạn có một nhóm các ngôn ngữ tương tự tại một thời điểm nhất định trong chương trình, bạn sẽ cần phải tách chúng ra tại một số điểm. Khi bắt đầu chương trình, bạn có thể muốn phân tách các ngôn ngữ sử dụng #làm điểm đánh dấu nhận xét khỏi các ngôn ngữ sử dụng một số điểm đánh dấu nhận xét khác. Sau này, có lẽ bạn có một điểm mà tất cả các ngôn ngữ sử dụng f(x)cú pháp cho các lệnh gọi hàm, tách các lệnh bằng dấu chấm phẩy và có sự tương đồng về cú pháp tương tự. Vào thời điểm đó, bạn có thể sử dụng một cái gì đó cụ thể hơn về ngôn ngữ để phân chia chúng, ví dụ như thực tế là Ruby và Perl không xử lý các chuỗi thoát trong ''chuỗi, nhưng Python và JavaScript thì có.

Nói chung, luồng logic của chương trình của bạn sẽ kết thúc dưới dạng cây, liên tục chia thành các nhóm ngôn ngữ giống nhau hơn so với nhau. Điều này đặt hầu hết những khó khăn trong việc viết polyglot ngay khi bắt đầu, trước khi phân tách đầu tiên. Khi luồng điều khiển phân nhánh ngày càng nhiều và các ngôn ngữ đang chạy tại bất kỳ điểm đã cho nào ngày càng giống nhau, nhiệm vụ của bạn sẽ dễ dàng hơn vì bạn có thể sử dụng cú pháp nâng cao hơn mà không khiến các ngôn ngữ liên quan đến lỗi cú pháp.

Một ví dụ điển hình là tập {JavaScript, Ruby, Perl, Python 3}; tất cả các ngôn ngữ này chấp nhận các lệnh gọi hàm với dấu ngoặc đơn và có thể phân tách các câu lệnh bằng dấu chấm phẩy. Tất cả chúng đều hỗ trợ một evaltuyên bố, cho phép bạn thực hiện kiểm soát dòng chảy một cách hiệu quả. (Perl là ngôn ngữ tốt nhất trong số các ngôn ngữ này được tách ra khỏi nhóm sớm, bởi vì nó có một cú pháp khác nhau cho các biến từ các ngôn ngữ khác.)


13

Ẩn mã bên trong chuỗi ký tự

Trong hầu hết các ngôn ngữ, một chuỗi ký tự tự nó không làm gì hoặc thực hiện một cái gì đó có thể dễ dàng đảo ngược (chẳng hạn như đẩy chuỗi lên ngăn xếp). Cú pháp chuỗi ký tự cũng tương đối không được chuẩn hóa, đặc biệt đối với các cú pháp thay thế mà nhiều ngôn ngữ sử dụng để xử lý các chuỗi có dòng mới được nhúng; ví dụ: Python có """ ... """, Perl có q( ... )và Lua có [[ ... ]].

Có hai công dụng chính của chúng. Một là cho phép bạn xen kẽ các phần dành cho các ngôn ngữ khác nhau thông qua việc bắt đầu một chuỗi ở cuối phần đầu tiên của một ngôn ngữ và tiếp tục nó ở đầu phần thứ hai: khá dễ dàng để tránh vô tình đóng chuỗi do sự đa dạng của chuỗi phân cách giữa các ngôn ngữ khác nhau. Một điều nữa là nhiều dấu phân cách chuỗi có ý nghĩa như một lệnh trong các ngôn ngữ khác (thường nhiều hơn các dấu nhận xét), vì vậy bạn có thể làm một cái gì đó giống như x = [[4] ], một phép gán vô hại trong các ngôn ngữ sử dụng ký hiệu JSON cho danh sách, nhưng bắt đầu một chuỗi trong Lua (và do đó cho phép bạn tách mã Lua khỏi phần còn lại, cho rằng nó có hiệu quả "nhảy" sang chuỗi tiếp theo ]]).


13

Kết thúc chương trình

Bạn có thể kết thúc chương trình đột ngột bằng một ngôn ngữ để nó sẽ bỏ qua mã trong ngôn ngữ khác.

Vì vậy, về cơ bản định dạng này có thể được sử dụng

code_in_language1 end_program_in_language1 code_for_language2 end_program_in_language2 ...

đâu end_program_in_languageNlà lệnh kết thúc chương trình.

Ví dụ, trong câu trả lời của tôi trong Bạn sẽ mang gì cho Lễ Tạ ơn? , Tôi đã kết thúc chương trình trong Dip, và sau đó tôi đã viết mã cho một ngôn ngữ khác, V, để trình thông dịch Dip sẽ bỏ qua nó.

"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

Nhưng sau đó, không phải tất cả các ngôn ngữ đều có một lệnh có thể kết thúc chương trình như vậy. Tuy nhiên, nếu một ngôn ngữ như vậy có tính năng, nó nên được sử dụng một cách khôn ngoan.

Như @LuisMendo đã đề xuất, bạn có thể tạo lỗi (nếu được phép) để kết thúc chương trình nếu ngôn ngữ chưa có nội dung "chương trình kết thúc".


2
Ngay cả khi ngôn ngữ không có chức năng hoặc tuyên bố kết thúc chương trình, một lỗi thường sẽ xảy ra
Luis Mendo

1
@LuisMendo: Đồng ý, mặc dù lưu ý rằng nhiều vấn đề đa hình đặc biệt cấm thoát-qua-sụp đổ vì nó làm cho mọi thứ quá dễ dàng. Tuy nhiên, đó là một ý tưởng tốt để khai thác nó khi họ không.

1
Bạn có lẽ nên đề cập rằng mã của phần thứ hai vẫn phải chính xác về mặt cú pháp trong ngôn ngữ thứ nhất hoặc nếu không, hầu hết các ngôn ngữ thực tế sẽ gây ra lỗi.
MilkyWay90

13

Biến hoặc mã bên trong chuỗi ký tự

Các chuỗi ký tự kép được trích dẫn chủ yếu là vô hại trong nhiều ngôn ngữ. Nhưng trong một số ngôn ngữ, chúng cũng có thể chứa mã.

Trong Bash, bạn có thể sử dụng `...`(nó không kết thúc chương trình):

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

Trong Tcl, bạn có thể sử dụng [...]:

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

Trong PHP, bạn có thể sử dụng ${...}(điều này tạo ra lỗi trong Bash để nó phải xuất hiện sau mã Bash):

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

Trong Ruby, bạn có thể sử dụng #{...}:

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

Cũng có thể có những người khác.

Những ngữ pháp này không tương thích. Điều đó có nghĩa là bạn có thể đặt tất cả mã của các ngôn ngữ này vào một chuỗi ở một vị trí vô hại. Và nó sẽ chỉ bỏ qua mã không được nhận dạng trong các ngôn ngữ khác và giải thích chúng là nội dung chuỗi.

Trong nhiều trường hợp, bạn cũng có thể dễ dàng nhận xét một ký tự trích dẫn kép ở đó và tạo một đa âm truyền thống hơn.


12

Biến răng cưa

Đây có lẽ là một trong những thủ thuật quan trọng nhất (IMO) đơn giản nhất để sử dụng, đặc biệt là vì nó có thể tiếp cận rất nhiều ngôn ngữ.

Thí dụ:

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

Điều này sẽ hoạt động trong không chỉ Javascript, mà cả Python, Ruby, v.v. Các ví dụ khác sau này khi tôi nghĩ về một số người khác. Tất nhiên, đề xuất bình luận / chỉnh sửa bài được chào đón.


5
Lưu ý rằng khi làm như JS / Python, nó thường là ngắn hơn để bí danh alertđể printtrong Python (3 chỉ) vì cú pháp bình luận JS của, //, có thể dễ dàng làm việc vào một chương trình Python, trong khi Python #không thể làm việc vào JS.
Sản phẩm ETH

11

#ý kiến ​​dựa trên

Mẹo này là một tập hợp con Khai thác các ký hiệu nhận xétBlockquote bằng ít nhất một ngôn ngữ

Khi tạo các đa âm với nhiều ngôn ngữ, đặc biệt là các ngôn ngữ sẵn sàng sản xuất trái ngược với esolang, có thể hữu ích khi xem các ngôn ngữ sử dụng #trong các nhận xét khối hoặc một dòng.

  • Có nhiều ngôn ngữ với các cú pháp nhận xét khối bắt đầu bằng #, và có rất nhiều loại ký tự theo sau #.
  • Hầu hết các ngôn ngữ này cũng cho phép một #nhận xét đơn lẻ , điều đó có nghĩa là một cái gì đó có thể bắt đầu một nhận xét khối trong một ngôn ngữ chỉ là một nhận xét thông thường trong một ngôn ngữ khác, làm cho nó dễ dàng phù hợp.

Dưới đây là danh sách tóm tắt nhanh các ngôn ngữ sử dụng #trong nhận xét khối (không đầy đủ):

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              #|          |#

Để biết thêm ví dụ, xem Mã Rosetta .

Đây là một ví dụ nhanh chóng và dễ dàng, như một minh chứng:

#|
###
#`[

print("Julia")
#=

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

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

]#
say "Perl 6"
#`[

...

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

Zephyr#- ... -#.
DLosc

11

Sai lệch toán tử số học

Đối với các ngôn ngữ tương tự hoặc các đa âm đơn giản, đôi khi thật hữu ích khi tìm kiếm sự khác biệt trong cách các ngôn ngữ thực hiện số học. Điều này là do hầu hết các ngôn ngữ (không bí truyền) có toán tử số học và số học có thể là một cách nhanh chóng và dễ dàng để giới thiệu sự khác biệt.

Ví dụ:

  • ^ là bitwise XOR trong một số ngôn ngữ và lũy thừa ở những ngôn ngữ khác
  • / là phép chia số nguyên trong một số ngôn ngữ và phép chia dấu phẩy động ở những ngôn ngữ khác
    • Đối với các ngôn ngữ phân chia số nguyên, -1/2-1trong một số ngôn ngữ (làm tròn xuống) và 0những người khác (tròn số không)
  • -1%2-1trong một số ngôn ngữ và 1trong người khác
  • --x là không có ngôn ngữ trong một số ngôn ngữ (phủ định kép) và giảm trước ở những ngôn ngữ khác
  • 1/0 đưa ra vô hạn trong một số ngôn ngữ và lỗi ở những ngôn ngữ khác
  • 1<<64cho 0 trong một số ngôn ngữ (tràn) và 36893488147419103232trong các ngôn ngữ khác

3
Một ví dụ đơn giản sẽ là x=1;["JS","Python"][--x], trả về tên của ngôn ngữ mà nó chạy trong (giữa JS và Python).
Sản xuất ETH

10

Sử dụng Brainfuck

Khá nhiều tất cả các triển khai BF bỏ ra các ký tự không +-<>[].,, điều này thực sự có lợi cho chúng ta!

BF có lẽ là một trong những ngôn ngữ dễ dàng nhất để hoạt động thành một polyglot vì tính năng này, miễn là bạn viết phần BF trước. Khi bạn đã viết mã BF, vấn đề là mô hình hóa bất kỳ mã nào khác bạn có xung quanh cấu trúc BF.

Đây là một ví dụ thực sự đơn giản:

.+[.+]

Điều này khá nhiều gia tăng và đầu ra charcode "mãi mãi" (tùy thuộc vào cài đặt thời gian chạy). Bây giờ nếu bạn muốn viết một đoạn mã ngẫu nhiên, giả sử, trong JS, bạn có thể làm:

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

Lưu ý cách JS được đúc xung quanh BF.

Hãy chắc chắn biết rằng điều này hoạt động tốt nhất nếu bạn thực sự bắt đầu với BF; thật khó để bắt đầu với một ngôn ngữ khác và cố gắng kết hợp BF.


6
Đối với các đa giác lớn hơn trong đó một vài byte tiết kiệm từ việc tích hợp BF không giúp được gì nhiều, tôi sẽ viết BF cuối cùng và bọc mã khác trong bao nhiêu []là cần thiết.
Sp3000

6
Điều này không chỉ áp dụng cho brainfuck mà còn với số lượng lớn các ngôn ngữ tương tự như brainfuck và rất nhiều tarpits Turing khác.
0 '

2
Cái đầu tiên x=>thay đổi tế bào, trong trường hợp này không thành vấn đề, nhưng chỉ muốn nói
Roman Gräf

7

Sử dụng ngôn ngữ mà hầu hết các ký tự không quan trọng

Đây là một khái quát về quan điểm của Mama Fun Roll về BF . Một esolang mà bỏ qua hầu hết các ký tự là rất hữu ích trong đa âm. Cũng hữu ích: một esolang trong đó một tập hợp lớn các ký tự có thể hoán đổi cho nhau. Vài ví dụ:

  • Khoảng trắng bỏ qua mọi thứ không phải là không gian, tab hoặc dòng mới.
  • Brain-Flak về cơ bản bỏ qua mọi thứ bên cạnh ()[]{}<>. ( @đôi khi gây ra lỗi khi trình thông dịch cố gắng phân tích nó như là bắt đầu của cờ gỡ lỗi.)
  • oOo CODE bỏ qua mọi thứ trừ các chữ cái. Hơn nữa, tất cả các chữ cái viết thường có thể hoán đổi cho nhau, cũng như tất cả các chữ cái viết hoa.
  • Wierd chỉ phân biệt giữa các ký tự khoảng trắng và ký tự không khoảng trắng.
  • Trong Wordy , một số ký tự dấu chấm câu bị bỏ qua và tất cả các chữ cái có thể hoán đổi cho nhau.
  • Cả ParentheticParent ngoặc Hell đều bỏ qua mọi thứ trừ dấu ngoặc đơn.

Tôi đã sửa @lỗi đó .
Thuật sĩ lúa mì

Hãy thử kết hợp khoảng trắng với Python
enedil

@enedil Bạn không cần phải có tab với Python. Bạn có thể sử dụngexec('''...\t\n\40''')
MilkyWay90

5

Hãy cảnh giác với các bình luận khối lồng nhau

Đôi khi, nhiều ngôn ngữ sẽ sử dụng cùng một cú pháp cho các bình luận khối, thường không phải là một công cụ giải quyết để tạo ra một polyglot với hai ngôn ngữ. Tuy nhiên, đôi khi, một trong những ngôn ngữ sẽ cho phép các bình luận khối lồng nhau, có thể bị lạm dụng để tạo các đường dẫn mã riêng biệt.

Ví dụ, hãy xem xét polyglot này:

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

Cả Nim và Lily đều sử dụng #[]#để bắt đầu và kết thúc bình luận khối, nhưng chỉ Nim cho phép bình luận khối lồng nhau.

Lily coi thứ hai #[là một phần của bình luận khối số ít và thứ nhất ]#là chấm dứt bình luận khối. ( #Tuyên bố in của Lily sau đây là một dòng chú thích ẩn mã của Nim.)

Nim thay thế, xem #[]#bình luận khối lồng nhau (mặc dù trống) và print("Lily")#là bình luận khối bên ngoài.


4

Không chắc chắn nếu điều này được tính, nhưng ...

Sử dụng một dòng shebang để biến mọi thứ thành một perlchương trình hợp lệ

Theo câu trả lời này và tài liệu Perl, nếu bạn chuyển bất kỳ tệp nào bắt đầu bằng dòng shebang sang perl, nó sẽ gọi chương trình thích hợp để chạy nó. Chẳng hạn, cái này

#!/usr/bin/python

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

được thực thi bởi trình thông dịch Python nếu bạn gọi perl filename.py.


3
Mặc dù chương trình có thể được gọi với perl, nhưng nó không trở thành chương trình Perl.
Paulo Ebermann

2
@ PaŭloEbermann Tôi nhận ra rằng đó là đường biên giới, đó là lý do tại sao tôi bắt đầu câu trả lời của mình với "không chắc nó có tính không". :) Nhưng điều gì định nghĩa Perl thật, nếu không phải là "những gì được viết trong tài liệu và được trả về bởi việc thực hiện tham chiếu perl"? Nghe có vẻ như một meme triết gia tốt ...
Federico Poloni


4

Gọi các hàm không tồn tại, sau đó thoát trong khi đánh giá các đối số của chúng

Nhiều ngôn ngữ lập trình có khả năng phân tích một mã định danh tùy ý theo sau là một cặp dấu ngoặc đơn với một biểu thức bên trong:

identifier(1 + 1)

Đôi khi, hình thức của mã định danh trong câu hỏi có thể được sửa chữa, do cần thiết để cung cấp mã cho một ngôn ngữ khác mà bạn đang sử dụng. Điều đó thoạt đầu có vẻ gây rắc rối, nếu định danh không tương ứng với chức năng mà ngôn ngữ thực sự có.

Tuy nhiên, nhiều ngôn ngữ lập trình sẽ đánh giá các đối số của hàm trước khi chúng kiểm tra xem liệu chính hàm đó có thực sự tồn tại hay không (ví dụ Lua), và vì vậy bạn vẫn có thể sử dụng loại cấu trúc này; tất cả những gì bạn cần là thoát khỏi chương trình ở đâu đó bên trong các đối số của hàm.

Dưới đây là một ví dụ, một polyglot dc / Lua:

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

c2pqlà một chương trình dc để in 2 và thoát; Lua coi đây là tên của một hàm, nhưng Lua có thể được ngăn chặn lỗi thông qua việc đặt lệnh thoát trong đối số của nó. Ưu điểm lớn của cấu trúc này là không giống như một phép gán ( c2pq =), nó không tự động không tương thích với các ngôn ngữ trong đó các tên biến bắt đầu bằng một sigil; Cú pháp tên hàm phù hợp hơn nhiều so với các ngôn ngữ so với cú pháp tên biến.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.