자체 포함 로그


16

"문제"

log호출 될 때 명령어 (소스로)와 첫 번째 인수를 모두 기록 / 인쇄 / 쓰기 (문제가되는 언어의 기본값이 무엇이든) 하는 함수 (또는 다른 3 글자 이름)를 정의하십시오 . 다시 말해:

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

모든 실제적인 목적으로 출력 i: 777은 충분하지만 일부 언어에는이를위한 매우 특정한 리플렉션 라이브러리가 있으며, 그다지 어렵지 않으므로 전체 명령을 출력해야합니다.

영감

이것에 대한 영감은 저와 다른 프로그래머가 (아주 나쁜 디버거를 사용하여) 자극하는 방법에 대해 논의했습니다 console.log("i:", i). 다음 과 같이 작성 i: 777합니다. 놀랍게도 길었고 코드 골프를 생각 나게하고 다른 (특히 코드 골프) 언어가 얼마나 더 나은지 궁금해했습니다.

보너스

-10 % : 파일을 읽지 않습니다 (컴파일러 이외)

추신. 이것은 나의 첫 번째 '질문'이므로, 내가 저지른 실수를 자유롭게 지적하십시오.


1
CodeGolf.SE에 오신 것을 환영합니다! 개인적으로 귀하의 질문은 꽤 괜찮다고 생각하지만, 사람들이 답변을 시작하기 전에 모호함 등을 해결하기 위해 샌드 박스 를 통해 질문 아이디어를 실행하는 것이 좋습니다 .
Martin Ender

Thx와 useful @ sandbox는 사용법을 설명하는 것이 좋을 수도 있습니다 help/on-topic(앞서 언급했지만 설명 된 방식을 확인할 가치는 없습니다.)
David Mulder

@ WolleVanillebärLutz : 물론 그렇지 않습니다. 그렇다면 누군가가 사실이라고 주장하는 것을 보셨습니까?
David Mulder

현상금은 TrungDQ입니다 (길이에 관계없이 코드 관점 (노드 전용 솔루션보다 낫습니다)에서 놀랍습니다). 24 시간을 기다려야 수여 할 수 있습니다.
David Mulder

답변:


14

C (40-10 % = 36) (38-10 % = 34.2)

C에서는 log함수를 특정 유형에 대해서만 정의 할 수 있습니다. 따라서이 log"함수"에는 int인수 만 사용됩니다 .

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

보다 일반적인 해결책은 인수 자체 외에도 인수를 인쇄하는 방법을 지정합니다.

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

예를 들어 lg2("%s", "I'm a string");또는 로 사용됩니다 lg2("%f", 3.1415).


나는 마지막 대괄호 x가 필요 하다고 생각하지 않습니다 .
user12205

@ace : 사용자가 인수에 이상한 문자를 넣으면 필요할 수도 있다고 생각했지만, 생각하면 맞습니다. 제거하겠습니다.
nneonneo

10

파이썬 (65-10 % = 58.5)

이것은 코드가 파일에 있다고 가정합니다 (대화식 인터프리터에서 호출되면 이상한 출력을 생성합니다).

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

Python 2.7.6에서 테스트되었습니다.

예:

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

log(foo())

출력

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
좋은! 말하고있어,이 프로그래머로 이해 나 (: O 기본 기능에 부정적인 인덱스) : 미친 물건의 종류 P의 오프 불가사의 일부 문서를 찾을 수
데이비드 멀더

9

C ++ 121 71 67 -10 % = 60.3

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

이런 식으로 사용 :

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

출력 :

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

C ++ : 대신 C로 작성하면 30 문자를 제거하고 하나의 라이너를 만들 수 #define log(x)printf("log(%s) %d\n",#x,x)있지만 정수의 경우에만 작동합니다.
user12205

@ace : 그런 다음 한 유형에서만 작동합니다. (또한 이것이 내가 제안한 솔루션입니다. 아래 참조)
nneonneo

@nneonneo 댓글을 게시하기 전에 새로 고침을 잊었을 때 미워합니다.
user12205

5

Rebol3-31.5 (35-10 %)

다음은 숫자에 잘 작동하는 @draegtun에서 단축 된 간단한 구현입니다.

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

실행하면 다음이 출력됩니다.

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

42.3 자 (47-10 %) 로 훨씬 더 유연 할 수 있습니다 (숫자가 아닌 유형의 형식을 표시하기 위해 )

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

출력 :

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

자바 스크립트 (325)

나는 이것이 log당신이 찾고 있는 기능 이라고 생각합니다 :

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()}

용법

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

산출

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

긴 코드

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

스크립트가 소스 코드를 얻기 위해 요청을 보내므로 문서 <script>에있는 태그 안에 스크립트가 삽입 된 경우에만 작동 합니다. JSfiddle, F12 Dev Tool Console, 임베드 된 파일이 작동하지 않습니다. 어디서나 사용할 수 있도록 노력 중입니다 ....htmllocation.href.js

어쨌든이 질문은 흥미 롭습니다.


나는 이것이 크로스 브라우저라는 것에 회의적입니다.
Farid Nouri Neshat

3

스칼라-(221-10 %) = 198.9

예이 매크로! 이것은 실제로 그들이 원하는 물건의 유형입니다.

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)}}

읽을 수있는 버전 :

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)
  }
}

예:

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

출력 :

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

추가는 스칼라에서 메소드 호출이므로 해당 구문을 다시 추가하지만 매우 가깝습니다! 다른 경우에는 좀 더 장황합니다.


와우, 그것은 기능의 추가를 보는 것이 매우 흥미 롭습니다. 배울 멋진 것들 : D
David Mulder

2

배쉬 (21-10 % = 18.9)

이:

alias log=echo;set -v

그런 다음 사용하는 log것처럼 사용하십시오 echo.

log $((1+1))

또는

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

이 방법은 필요한 모든 것을 수행합니다. 보너스로 일부 추가 정보도 인쇄되지만 명시적인 규칙은 금지하지 않습니다.


2

세게 때리다

인수는 BASH에서 "(...)"을 사용하여 전달되지 않으므로 'log ()'의 출력이 해당 스타일에 맞도록하십시오.

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

$((...))할 수 있습니다 $[...]대신하지만 지금까지 문제가되지 않습니다 그래서 나는 문자를 계산하지 않았다.

2

클로저

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

동질성에는 장점이 있습니다!

쓰다:

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

무슨 일이 일어나고 있는지 보자 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__))

당신이 인용한다면 x, 당신은 정말로 중간 유전자 (즉,)를 사용해야 x#합니까? 나는 (BTW, 내가 더 Clojure의 전문가입니다 없음) 후에는 표현식을 평가만을 생각
코어 덤프

2

줄리아, 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

또는 규칙을 준수하지 않는 경우

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}

용법:

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

편집 : 작은 개선


0

커먼 리스프-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)))))
  • 표준 로그 함수 @이기 때문에 이름 log이 지정되고 기본적으로 잠겨 있습니다 (적어도 SBCL에서). 또한 @한 문자 길이입니다.
  • A와 작용 progn가변 인자를 고려하지만, 표준 출력 인쇄물. 실제 응용 프로그램에서는 아마도signal 공백으로 구분 된 출력을 인쇄하는 대신 S- 표현식이있는 조건 .
  • 기존 Clojure 솔루션과 달리 궁극적으로 기록 된 표현식의 값을 반환하므로 (@ x)언제든지 사용할 수 있습니다.x .
  • 인쇄는을 사용 prin1하여 read문자열 을 출력 합니다. 이것은 로그 된 표현식을 재현 할 때 유용합니다.
  • 가능한 모든 유형을 처리합니다 (C 답변 참조)
  • 여러 값을 고려합니다
  • 다른 출력을 생성하지 않습니다 (스칼라 답변 참조)
  • 파일과 REPL에서 작동합니다 (Pyhton 답변 참조).
  • 브라우저 / 인터프리터 트릭이 필요하지 않습니다 (Python 추적, Javascript 요청)

샘플 출력 :

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

마지막으로 위의 내용을 기록 defmacro하면 ungolfed 버전이 있습니다.

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

log다른 모듈 ( APD) 을 사용하지 않고 PHP에서 다시 선언 할 수 없으므로 logg대신 사용 했습니다 log. 필요한 경우 예제로 다시 제출할 수 있습니다 . 그것은 사소하지만, 더 죄악 나는 이것이 로그 기능이 그 자체로 줄에 있다고 가정한다는 것입니다. 의견에 따라 답변을 업데이트 할 수 있습니다.

<?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";}

출력 예 :

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

자바 스크립트 55 53

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

용법:

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

산출:

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

큰 따옴표를 사용해야합니다. "그렇지 않으면 작동하지 않습니다.


내가 제공 한 예제 의사 코드를 따르지 않음으로써 규칙을 이미 굽히지 않더라도 더 큰 문제는 변수가 전역 컨텍스트에 정의 된 경우 에만 작동한다는 것입니다 (평가 평가 컨텍스트가 그보다 복잡하다는 것을 알고 있습니다.
David Mulder

도전의 요점은 당신이 문자열을 전달하지 않았다는 것입니다 ... -1
Doorknob

요점은하지 않았다 log("i:", i)... 나는 그것이 없으면 할 수 없다고 생각한다'" js 또는 js로 ... 당신은 그것을 사용하여 더 작게 만들 수 console.log('log('+o+')'+eval(x))있지만 출력은 코드 라인 (관심있는 사람)과 일치하지 않습니다
rafaelcastrocouto

2
한 줄로 할 수 있습니다. 노드에서 어떻게 했습니까? 오류를 발생시키고 스택을 가져오고 파일을 읽고 행을 추출합니다. 그래, 좀 미쳤어 : D. 또한을 사용하여 가능할 수도 arguments.callee.caller.toString()있지만 두 개의 로그가있을 때 어떤 줄이 어느 것인지 알아낼 수 없었습니다.
David Mulder
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.