2010-09-04 6 views
6

Khi bạn đang gỡ lỗi, nó rất hữu ích để làm điều này:Làm cách nào để in tên biến và giá trị của tên mà không cần nhập tên hai lần?

var = calc() 
print("var:", var) 

Có bất kỳ ngôn ngữ nơi này rất dễ dàng để làm gì? Trong C và C++ bạn có thể sử dụng stringify vĩ mô điều hành # và trong Ruby Tôi tìm thấy câu hỏi này:

Ruby - print the variable name and then its value

Các giải pháp mà sử dụng một biểu tượng: var và một khối là những gì tôi muốn.

Trong D, tôi đã sử dụng này:

void trace(alias msg)() { 
    writeln(msg.stringof ~ ":" ~ to!string(msg)); 
} 

Nhưng tôi không chắc đó là cách tốt nhất, bởi vì nó chỉ có tác dụng trong những trường hợp đơn giản. Tôi đã thử một số cách, nhưng đôi khi bạn có thể nhận được chuỗi, nhưng không phải là giá trị (vì biến nằm ngoài phạm vi), hoặc bạn phải trộn mẫu trước và sau đó gọi hàm.

Và còn các ngôn ngữ khác thì sao? Python? F #? Boo? Shell script (bất kể shell nào)? Perl? (Tôi thích tránh xa Perl, tho). Tcl? Lisp, Đề án? Java? (Java rất khó có thể làm được điều này).

Ngay cả trong các ngôn ngữ mà tôi tìm thấy một số loại giải pháp, nó chỉ hoạt động đối với các trường hợp đơn giản. Nếu tôi muốn in một biểu thức tùy ý thì sao?

Nếu tôi thiết kế một ngôn ngữ, tính năng này sẽ là một tính năng không thể thiếu. :-)

Trả lời

5

Đây là một cách rất chung chung, nhưng hơi xấu xí để làm điều đó trong D, sử dụng biên dịch chức năng đánh giá thời gian (CTFE) để tạo mã như là một chuỗi theo nghĩa đen, và một tuyên bố mixin để đánh giá nó:

import std.stdio, std.math; 

// CTFE function that generates trace code. 
string trace(string varName) { 
    return "writeln(\"" ~ varName ~ ": \", " ~ varName ~ ");"; 
} 

void main() { 
    // Trace a function call. 
    mixin(trace("sqrt(5)")); 

    // Trace a variable. 
    int foo = 5; 
    mixin(trace("foo")); 
} 

Các vấn đề duy nhất là nhập bằng tay mixin ở khắp mọi nơi là tiết và bất cứ điều gì bạn muốn theo dõi cần phải ở bên trong một chuỗi chữ xấu xí. Lưu ý rằng có hai loại mixin trong D. Các mixin mẫu được xử lý tốt hơn theo nhiều cách, nhưng các mixin chuỗi (được sử dụng trong ví dụ này) là tổng quát như nó được, trong đó bất kỳ mã nào có thể về nguyên tắc được tạo thông qua CTFE và sau đó trộn vào.

+0

Tuyệt vời! Đó chính xác là những gì tôi cần! Cảm ơn! Các trích dẫn cần thiết là tinh tế, phải không? Quá xấu D không cho phép nội suy varName để làm cho nó trông sạch hơn. Tôi không nhớ đặt biểu thức bên trong một chuỗi (tôi có thể sử dụng q {} để có mã thông báo hiliting trong trình soạn thảo của tôi). Đối với verbosity, tôi có thể sử dụng một tên hàm rất ngắn :-) – marcus

2

Không quan trọng trong bất kỳ Lisp nào. Trong vợt (Đề án PLT nhũ):

(define-syntax-rule (debug-info expr) 
    (format "~a is ~a" (quote expr) expr)) 

(let ((long-boring-name 5)) 
    (display (debug-info long-boring-name))) 

# displays "long-boring-name is 5" 

(let ((fifty-two 52)) 
    (display (debug-info (+ fifty-two 6)))) 

# displays "(+ fifty-two 6) is 58" 
0

tôi xem xét Tcl cơ bản "Lisp mà không cần bất kỳ cấu trúc dữ liệu" (với chuỗi thay vì ... tốt, khá nhiều bất cứ điều gì, thực sự), do đó, nó gần như là dễ dàng trong Tcl như trong Lisp.

Nó được một vài năm, nhưng tôi nghĩ rằng một cái gì đó như thế này sẽ làm các trick:

proc log_var {var} { 
    upvar 1 $var x 
    puts "$var is: $x" 
} 

set my_var 5 
log_var my_var 

Tôi nghĩ rằng có lẽ là một cách để sử dụng uplevel để mở rộng này để làm việc cho các biểu thức tùy ý.

+0

tôi chưa bao giờ được lập trình trong Tcl trước (tôi đã biết cú pháp cơ bản của ngôn ngữ), nhưng sau gợi ý của bạn tôi đến với điều này: proc log_expr {exp} { bộ x [uplevel 1 $ exp] BREAK_LINE_HERE đặt "$ exp là: $ x" } log_expr {expr 1 + 1} NÀY LÀ TUYỆT VỜI !!!! – marcus