自己完結型ログ


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)我々は(ノードのみ)ソリューションは、(それが出力する(かなりクレイジー)JavaScriptを作っ横、i: 777行全体ではなく、出典)これは驚くほど長く、コードゴルフを思い出させて、他の(特にコードゴルフ)言語がどれほど優れているかと思いました。

ボーナス

-10%:ファイル読み取りなし(コンパイラーを超えて)

PS。これがここでの私の最初の「質問」なので、私が犯した間違いを気軽に指摘してください。


1
CodeGolf.SEへようこそ!個人的にはあなたの質問はかなりまともだと思いますが、通常は質問のアイデアをサンドボックスに通しあいまいさなどを解決してから回答に取り掛かる方が良いでしょう。
マーティンエンダー14年

Thxとuseful @ sandboxは、それが使用されていることを説明するのに良いかもしれませんhelp/on-topic(言及されていますが、そこに記述されている方法を確認する価値はないと考えました)。
デビッドモルダー14年

@WolleVanillebärLutz:もちろんそうではありませんが、あなたはその時真実だと主張する人を見ましたか?
デビッドモルダー14年

報奨金はTrungDQ(長さに関わらず、コードの観点から(私たちのノードのみのソリューションよりも優れている)彼のソリューションは素晴らしいと思います)、24時間待つ必要があります。
デビッドモルダー14年

回答:


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

@ace:ユーザーが引数に奇妙な文字を入力した場合に必要になると思いましたが、反省するとあなたは正しいと思います。それらを削除します。
nneonneo

10

Python(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 はいくつかのドキュメントを見つけるために不思議に思っています
David Mulder 14年

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

@ace:1つのタイプに対してのみ機能します。(また、これは私が提案された解決策は、以下の参照である)
nneonneo

@nneonneoコメントを投稿する前に更新するのを忘れたときは嫌いです。
user12205 14年

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

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

とにかく、この質問は興味深いです。


私はこれがクロスブラウザであることに少し懐疑的です。
ファリッドノウリネシャット14年

3

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

追加はScalaのメソッド呼び出しであるため、その冗長な構文が追加されますが、かなり近いです!また、他のいくつかのケースではもう少し冗長です。


うわー、関数の追加を見るのはとても興味深いです。学ぶべきものがたくさんあります:D
デビッドモルダー14年

2

bash(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する場合、中間のgensym(つまりx#)を使用する必要が本当にありますか?式を評価するのは一度だけだと思います(ところで、私はClojureの専門家ではありません)
coredump

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

Common Lisp-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の)デフォルトでロック。また、@1文字のみです。
  • progn可変数の引数をとるa として機能しますが、標準出力に出力します。実際のアプリケーションでは、signalスペースで区切られた出力を印刷する代わりに、おそらくS式を使用した条件になります。
  • 既存のClojureソリューションとは異なり、ログに記録された式の値を最終的に返すので、(@ x)いつでも使用できますx
  • 印刷ではprin1read-able文字列を出力します。これは、ログに記録された式を再現するときに役立ちます。
  • 可能なすべてのタイプを処理します(Cの回答を参照)
  • 複数の値を考慮に入れる
  • 異なる出力を生成しません(Scalaの回答を参照)
  • ファイルおよび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、私は未ゴルフバージョンを持っています:

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

JavaScript 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

二重引用符を使用する必要があります"。そうしないと機能しません。


私が提供したサンプルの擬似コードに従わないことですでにルールを曲げているにもかかわらず、より大きな問題は、変数がグローバルコンテキストで定義されている場合にのみ機能することです(eval評価コンテキストはそれよりも複雑であることがわかっています、しかしポイントスタンド)
デビッドモルダー14年

課題のポイントは、文字列を渡さないことです... -1
ドアノブ

ポイントはやっていませんでしたlog("i:", i)...私はそれをせずに行うことができないとは思わない'か、"jsの中で...あなたはそれが小さく使用することができますconsole.log('log('+o+')'+eval(x))が、出力は、コード行(苦労)が一致しません
rafaelcastrocouto

2
あなたは一行でそれを行うことができます、私はノードでそれをしました、どうですか?エラーをスローし、スタックを取得し、ファイルを読み取り、行を抽出します。うん、ちょっとクレイジー:D。さらに、を使用して可能かもしれませんがarguments.callee.caller.toString()、2つのログがある場合、どの行がどの行であるかを把握できませんでした。
デビッドモルダー14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.