Nhật ký tự chứa


16

Vấn đề"

Xác định một hàm log(hoặc 3 tên chữ cái khác) mà khi được gọi sẽ ghi / in / ghi (bất cứ thứ gì là mặc định cho ngôn ngữ trong câu hỏi) cả hướng dẫn (dưới dạng nguồn) và đối số đầu tiên. Nói cách khác:

i=777
j=333
log(i) //outputs: "log(i) 777"
log(i+j+1) //outputs: "log(i+j+1) 1111"

Đối với tất cả các mục đích thực tế, đầu ra i: 777sẽ là đủ, nhưng trong một số ngôn ngữ có các thư viện phản ánh rất cụ thể cho điều đó, và đó sẽ không phải là thách thức, vì vậy toàn bộ hướng dẫn nên được xuất ra.

Cảm hứng

Cảm hứng cho điều này là tôi và một lập trình viên khác thảo luận về việc nó thường gây khó chịu như thế nào (với trình gỡ lỗi xấu), bạn viết những thứ như console.log("i:", i), tiếp theo chúng tôi đã tạo ra một giải pháp javascript (chỉ nút) (nó chỉ xuất ra i: 777thay vì toàn bộ dòng nguồn) đã kéo dài đáng kinh ngạc và nhắc nhở tôi về việc mã hóa và khiến tôi tự hỏi rằng các ngôn ngữ khác (đặc biệt là chơi gôn) sẽ tốt hơn bao nhiêu.

Tiền thưởng

-10% : Không đọc tệp (ngoài trình biên dịch)

Tái bút Đây là "câu hỏi" đầu tiên của tôi ở đây, vì vậy hãy thoải mái chỉ ra bất kỳ sai lầm nào tôi đã mắc phải.


1
Chào mừng bạn đến với CodeGolf.SE! Cá nhân tôi nghĩ rằng câu hỏi của bạn khá hay, nhưng thường là một ý tưởng tốt hơn để chạy các ý tưởng câu hỏi thông qua hộp cát để giải quyết sự mơ hồ, vv trước khi mọi người bắt đầu trả lời.
Martin Ender

Thx và hữu ích @ sandbox, có thể tốt để giải thích về việc sử dụng help/on-topicnó (nó đã được đề cập, nhưng tôi không cho rằng nó đáng để kiểm tra cách nó được mô tả ở đó).
David Mulder

@ WolleVanillebärLutz: Tất nhiên là không, bạn có thấy ai khẳng định điều đó là đúng không?
David Mulder

Tiền thưởng dành cho TrungDQ (Tôi nghĩ rằng giải pháp của anh ấy thật tuyệt vời chỉ từ góc độ mã (tốt hơn giải pháp chỉ nút của chúng tôi), bất kể độ dài), phải đợi 24 giờ trước khi tôi có thể trao giải.
David Mulder

Câu trả lời:


14

C (40 -10% = 36) (38 -10% = 34,2)

Lưu ý rằng, trong C, một loghàm chỉ có thể được xác định cho một loại cụ thể. Do đó, log"hàm" này chỉ lấy các intđối số.

#define log(x)printf("log("#x") %d",x)

Một giải pháp tổng quát hơn chỉ định cách in đối số, ngoài chính đối số:

#define lg2(f,x)printf("lg2("#x") "f,x)

mà sẽ được sử dụng như ví dụ lg2("%s", "I'm a string");hoặc lg2("%f", 3.1415).


Tôi không nghĩ rằng dấu ngoặc cuối cùng xlà cần thiết.
dùng12205

@ace: Tôi nghĩ rằng chúng có thể cần thiết nếu người dùng đưa vào một số ký tự kỳ lạ trong đối số, nhưng khi phản ánh tôi nghĩ bạn đã đúng. Tôi sẽ loại bỏ chúng.
nneonneo

10

Con trăn (65 -10% = 58,5)

Điều này giả sử mã của bạn nằm trong một tệp (nó tạo ra đầu ra lẻ nếu được gọi trong trình thông dịch tương tác):

import traceback as t
def log(x):print t.extract_stack()[-2][3],x

Nó đã được thử nghiệm trên Python 2.7.6.

Thí dụ:

def foo():
    x = 1
    log(x)
    for i in xrange(10):
        log(x+i+1)
    return x

log(foo())

đầu ra

log(x) 1
log(x+i+1) 2
log(x+i+1) 3
log(x+i+1) 4
log(x+i+1) 5
log(x+i+1) 6
log(x+i+1) 7
log(x+i+1) 8
log(x+i+1) 9
log(x+i+1) 10
log(x+i+1) 11
log(foo()) 1

1
Đẹp! Phải nói rằng, đây là loại công cụ điên rồ khiến tôi quan tâm như một lập trình viên (chỉ số tiêu cực về chức năng bản địa: O): P tự hỏi để tìm một số tài liệu
David Mulder

9

C ++ 121 71 67 -10% = 60.3

#include<iostream>
#define log(x)std::cout<<"log("#x") "<<(x)<<"\n"

Được sử dụng như thế này:

int main() {
    int i = 777;
    int j = 333;
    log(i);
    log(i+j+1);
}

Đầu ra:

log(i) 777
log(i+j+1) 1111

Bạn có thể xóa 30 char và tạo một lớp lót nếu bạn viết nó bằng C thay vì C ++: #define log(x)printf("log(%s) %d\n",#x,x)nhưng điều đó sẽ chỉ hoạt động với các số nguyên.
dùng12205

@ace: sau đó nó chỉ hoạt động cho một loại. (Ngoài ra, đây là giải pháp tôi đề xuất, xem bên dưới)
nneonneo

@nneonneo Tôi ghét nó khi tôi quên làm mới trước khi đăng bình luận.
dùng12205

5

Rebol3 - 31,5 (35 - 10%)

Đây là một triển khai đơn giản rút ngắn từ @draegtun hoạt động tốt cho các số:

log: func[p][print[{log[}p{]}do p]]

Chạy nó đầu ra:

>> log: func[p][print[{log[}p{]}do p]]
>> i: 777
>> j: 333
>> log [i]
log[ 777 ] 777
>> log[i + j + 1]
log[ i + j + 1 ] 1111

Nó có thể linh hoạt hơn nhiều (để hiển thị dạng các loại không số) ở mức 42,3 ký tự (47 - 10%)

log: func[p][print[{log}mold p mold/only do p]]

Đầu ra:

>> log: func[p] [print[{log}mold p mold/only do p]]
>> log [join "4" 4]
log [join "4" 4] "44"  ;; shows a string
>> log [1 + 2]
log [1 + 2] 3 

4

Javascript (325)

Tôi nghĩ rằng đây là logchức năng bạn đang tìm kiếm:

function log(m){L=(new Error()).stack.match(/(at log \([\s\S]+?at .+?:)\d+:\d+/m)[0].split('\n')[1].match(/:\d+:\d+/)[0];N=L.split(':')[1];C=parseInt(L.split(':')[2]);R=new XMLHttpRequest();R.open('GET',location.href,0);R.onload=function(){console.log(R.response.split('\n')[N-1].substr(C-1).split(';')[0]+' = '+m)};R.send()}

Sử dụng

<script>
function log(m){L=(new Error()).stack.match(/(at log \([\s\S]+?at .+?:)\d+:\d+/m)[0].split('\n')[1].match(/:\d+:\d+/)[0];N=L.split(':')[1];C=parseInt(L.split(':')[2]);R=new XMLHttpRequest();R.open('GET',location.href,0);R.onload=function(){console.log(R.response.split('\n')[N-1].substr(C-1).split(';')[0]+' = '+m)};R.send()}

function doSomething() {
  var a = 123; log(a); var b = "Hello, I am TrungDQ!"; log(b);
}
doSomething();
var message = "...or just do it out here";
log(message + "!");
</script>

Đầu ra

log(a) = 123
log(b) = Hello, I am TrungDQ!
log(message + "!") = ...or just do it out here!

Mã dài

<script>
function log(msg) {
  // Get the line number and offset of the line where is function is called
  var lineInfo = (new Error()).stack.match(/(at log \([\s\S]+?at .+?:)\d+:\d+/m)[0].split('\n')[1].match(/:\d+:\d+/)[0];
  var lineNum = lineInfo.split(':')[1];
  var charOffset = parseInt(lineInfo.split(':')[2]);

  // Get the file source
  request = new XMLHttpRequest();
  request.open('GET', window.location.href, true);

  request.onload = function() {
    // Get file source code
    var response = request.responseText;
    // Get the `log` line
    var line = response.split('\n')[lineNum - 1];
    // Get the `log` statement
    var logStatement = line.substr(charOffset - 1).split(';')[0];
    // Print it
    console.log(logStatement + ' = ' + msg);
  };
  request.send();
}

function doSomething() {
  var a = 123; log(a); var b = "Hello, I am TrungDQ!"; log(b);
}
doSomething();
</script>

Chỉ hoạt động khi tập lệnh được đặt bên trong <script>thẻ được đặt trong .htmltài liệu vì nó sẽ gửi yêu cầu location.hreflấy mã nguồn. JSfiddle, Bảng điều khiển công cụ Dev F12, .jscác tệp được nhúng sẽ không hoạt động, tôi đang cố gắng làm cho nó có sẵn ở mọi nơi ...

Dù sao, câu hỏi này là thú vị.


Tôi hơi nghi ngờ đây là trình duyệt chéo.
Farid Nouri Neshat

3

Scala - (221 - 10%) = 198,9

Macro Yay! Đây thực sự chính xác là loại công cụ họ dành cho.

import language.experimental.macros
def log(p:Any)=macro l
def l(c:reflect.macros.Context)(p:c.Expr[Any])={import c.universe._;reify{println("log("+(c.Expr[String](Literal(Constant(show(p.tree)))).splice)+") "+p.splice)}}

Phiên bản dễ đọc:

import language.experimental.macros
def log(p: Any) = macro l
def l(c: reflect.macros.Context)(p: c.Expr[Any]) = {
  import c.universe._
  val inputString = show(p.tree)
  val inputStringExpr = c.Expr[String](Literal(Constant(inputString)))
  reify {
    println("log(" + (inputStringExpr.splice) + ") " + p.splice)
  }
}

Thí dụ:

log(1)
val x = 3
log(x)
val y = 4
log(x+y)

Đầu ra:

log(1) 1
log(x) 3
log(x.+(y)) 7

Vì phép cộng là một cuộc gọi phương thức trong Scala, nó thêm cú pháp dài dòng đó trở lại, nhưng nó khá gần! Nó cũng dài dòng hơn một chút trong một vài trường hợp khác.


Ồ, thật thú vị khi thấy @ bổ sung chức năng. Quá nhiều thứ hay ho để học: D
David Mulder

2

bash (21 - 10% = 18,9)

Điều này:

alias log=echo;set -v

Sau đó sử dụng lognhư bạn sẽ sử dụng echo:

log $((1+1))

hoặc là

A=2
B=3
log $((A+B))

Phương pháp này sẽ làm tất cả những gì được yêu cầu; như một phần thưởng, một số thông tin bổ sung cũng sẽ được in, nhưng không có quy tắc rõ ràng nào cấm nó.


2

BASH

Các đối số không được truyền bằng cách sử dụng "(...)" trong BASH, vì vậy tôi để đầu ra của 'log ()' phù hợp với kiểu đó:

$ log(){ echo "$FUNCNAME $@: $(($@))"; }
$ i=333
$ j=777
$ log i
log i: 333
$ log i+j+1
log i+j+1: 1111

$((...))có thể $[...]thay vào đó nhưng tôi đã không đếm số ký tự, vì vậy cho đến giờ nó không còn quan trọng nữa.

2

Clojure

(defmacro log[x] `(let [x# ~x] (println "log("'~x")" x#)))

Homoiconicity có lợi ích của nó!

Để sử dụng:

(def i 777)
(def j 333)
(log i) ;Prints log( i ) 777
(log (+ i j 1)) ;Prints log( (+ i j 1) ) 1111

Hãy xem điều gì đang xảy ra với macroexpand:

(macroexpand '(log (+ i j 1))) 
;; Prints the following: 
(let* [x__1__auto__ (+ i j 1)] (clojure.core/println "log(" (quote (+ i j 1)) ")" x__1__auto__))

Nếu bạn trích dẫn x, bạn có thực sự cần phải sử dụng một gensym trung gian (tức là. x#)? Tôi nghĩ rằng bạn sẽ chỉ đánh giá biểu thức một lần (btw, tôi không phải là chuyên gia Clojure)
coredump

2

Julia, 51 * 0,9 = 45,9

julia> x=4
4
julia> macro log(x) println("log($x) $(log(eval(x)))") end
julia> @log(x)
log(x) 1.3862943611198906

Ngoài ra, nhưng không đáp ứng các quy tắc

julia> @show log(x)
log(x) => 1.3862943611198906

2

Tcl, 42,3 (47 - 10%)

proc log c {puts [dict g [info fr -1] cmd]\ $c}

Sử dụng:

set i 777
set j 333
log $i  ;#outputs: "log $i 777"
log [expr {$i+$j+1}] ;#outputs: "log [expr {$i+$j+1}] 1111"

Chỉnh sửa : cải thiện nhỏ


0

Lisp thường gặp - 119,7 (133 -10%)

(defmacro @(&whole f &rest r)(let((g(gensym)))`(let((,g(multiple-value-list,@r)))(progn(format t"~s~{ ~a~}
"',f,g)(values-list,g)))))
  • Được đặt tên @bởi vì loglà hàm logarit tiêu chuẩn và được khóa theo mặc định (ít nhất là trên SBCL). Ngoài ra, @chỉ dài một ký tự.
  • Hoạt động như một progn, lấy một số lượng đối số khác nhau, nhưng in ra đầu ra tiêu chuẩn. Trong các ứng dụng thực tế, tôi có thể sẽ có signalmột điều kiện với biểu thức S thay vì in đầu ra được phân tách bằng dấu cách.
  • Trái với giải pháp Clojure hiện có, cuối cùng chúng ta trả về giá trị của biểu thức đã ghi, do đó (@ x)có thể được sử dụng bất cứ khi nào xđược sử dụng.
  • Sử dụng in ấn prin1, mà đầu ra mộtread chuỗi -able. Điều này rất hữu ích khi cố gắng tái tạo các biểu thức đã ghi.
  • Xử lý tất cả các loại có thể (xem câu trả lời C)
  • Đưa vào các giá trị đột biến
  • Không tạo ra kết quả đầu ra khác nhau (xem câu trả lời của Scala)
  • Hoạt động từ một tệp và từ REPL (Xem câu trả lời của Pyhton)
  • Không yêu cầu thủ thuật trình thông dịch / trình thông dịch (truy nguyên Python, yêu cầu Javascript)

Đầu ra mẫu:

CL-USER>(@ (+ 3 2))   ; user input
(@ (+ 3 2)) 5         ; printed output
5                     ; result of expression

CL-USER> (@ (values 3 4))  ; input
(@ (VALUES 3 4)) 3 4       ; logging
3                          ; first value
4                          ; second value

CL-USER>(@ (round 3.4))
(@ (ROUND 3.4)) 3 0.4000001
3                          ; rounded value
0.4000001                  ; delta

Và cuối cùng, nếu tôi đăng nhập ở trên defmacro, tôi có phiên bản không được chỉnh sửa:

CL-USER> (@ (defmacro @(&whole f &rest r)(let((g(gensym)))`(let((,g(multiple-value-list,@r)))(progn(format t"~s~{ ~a~}
"',f,g)(values-list,g))))))
STYLE-WARNING: redefining COMMON-LISP-USER::@ in DEFMACRO
(@
 (DEFMACRO @ (&WHOLE F &REST R)
   (LET ((G (GENSYM)))
     `(LET ((,G (MULTIPLE-VALUE-LIST ,@R)))
        (PROGN
         (FORMAT T ,"~s~{ ~a~}
"
                 ',F ,G)
         (VALUES-LIST ,G)))))) @
@ ; actual result

0

PHP 138

Bạn không thể tái phân phối logtrong PHP mà không sử dụng mô-đun khác ( APD) vì vậy tôi đã sử dụng loggthay thế, tôi có thể gửi lại với logví dụ nếu cần. Điều đó nhỏ, nhưng tội lỗi hơn tôi đoán là điều này giả sử chức năng đăng nhập nằm trên một dòng. Tôi có thể cập nhật câu trả lời của mình như được đưa ra bởi các bình luận.

<?php function logg($v){$b=debug_backtrace()[0];$h=fopen($b['file'],"r");for($i=0;$i<$b['line']&&$l=fgets($h);$i++);echo trim($l)." $v";}

đầu ra ví dụ:

for ($i=1; $i<10; $i++) {   
  $j=$i+1;
  $k=$j+1;
  logg($i+$j+$k);
  echo "\n";
}
/*
logg($i+$j+$k); 6
logg($i+$j+$k); 9
logg($i+$j+$k); 12
logg($i+$j+$k); 15
logg($i+$j+$k); 18
logg($i+$j+$k); 21
logg($i+$j+$k); 24
logg($i+$j+$k); 27
logg($i+$j+$k); 30
*/

-2

JavaScript 55 53

function log(x){console.log('log("'+x+'") '+eval(x))}

Sử dụng:

var i = 777,
    j = 333;
log("i")
log("j")
log("12*4")
log("i*j-4")

Đầu ra:

log("i") 777
log("j") 333
log("12*4") 48
log("i*j-4") 258737

Bạn PHẢI sử dụng dấu ngoặc kép "nếu không nó sẽ không hoạt động.


Bất kể nó đã bẻ cong các quy tắc bằng cách không tuân theo mã giả ví dụ mà tôi đã cung cấp, vấn đề lớn hơn là nó chỉ hoạt động khi và chỉ khi các biến được xác định trong bối cảnh toàn cầu (Tôi biết bối cảnh đánh giá eval phức tạp hơn thế, nhưng điểm đứng)
David Mulder

Điểm chính của thử thách là bạn không vượt qua một chuỗi ... -1
Doorknob

Vấn đề là không làm log("i:", i)... Tôi không nghĩ rằng nó không thể được thực hiện mà không có 'hoặc "trong js ... bạn có thể làm cho nó nhỏ hơn bằng cách sử dụng console.log('log('+o+')'+eval(x))nhưng đầu ra sẽ không khớp với dòng mã (ai quan tâm)
rafaelcastrocouto

2
Bạn có thể làm điều đó trong một dòng duy nhất, tôi đã làm nó trong nút, làm thế nào? Bằng cách ném một lỗi, nhận ngăn xếp, đọc tệp và trích xuất dòng. Đúng, hơi điên: D. Ngoài ra, có thể sử dụng được arguments.callee.caller.toString(), nhưng tôi không thể tìm ra dòng nào là khi bạn có hai bản ghi.
David Mulder
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.