Kendinden içeren günlükler


16

Sorun"

Çağrıldığında, loghem komutu (kaynak olarak) hem de ilk bağımsız değişkeni günlüğe yazdıracak / yazacak / yazacak (söz konusu dil için varsayılan ne olursa olsun) bir işlev (veya başka bir 3 harf adı) tanımlayın . Diğer bir deyişle:

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

Tüm pratik amaçlar için çıktı i: 777yeterli olacaktır, ancak bazı dillerde bunun için çok özel yansıma kütüphaneleri vardır ve bu hiç de zor olmayacaktır, bu nedenle tüm talimatın çıktısı alınmalıdır.

İlham

Bunun için ilham kaynağı ben ve başka bir programcıydı (sık sık hata ayıklayıcılarla), ne kadar sinir bozucu olduğunu tartışıyorduk, bir şeyler yazıyorsunuz console.log("i:", i), daha sonra (oldukça çılgın) bir javascript (sadece düğüm) çözümü yaptık ( i: 777tüm satırdan ziyade çıktılar) kaynak) şaşırtıcı derecede uzun ve bana codegolfing hatırlattı ve diğer (özellikle kod golf) dillerin daha iyi olacağını merak yaptı.

Bonuslar

-10% : Dosya okuma yok (derleyicinin ötesinde)

PS. Bu benim ilk 'sorum', bu yüzden yaptığım hataları belirtmekten çekinmeyin.


1
CodeGolf.SE'ye hoş geldiniz! Şahsen sorunuzun oldukça iyi olduğunu düşünüyorum, ancak insanlar cevaplar üzerinde çalışmaya başlamadan önce belirsizlikleri vb. Çözmek için sanal alanda soru fikirleri çalıştırmak daha iyi bir fikirdir .
Martin Ender

Thx ve yararlı @ sandbox, kullanımı açıklamak için iyi olabilir help/on-topic(bahsedildi, ancak orada açıklandığı şekilde kontrol etmeye değer olduğunu düşünmedim).
David Mulder

@ WolleVanillebärLutz: Elbette öyle değil, o zaman bunun doğru olduğunu iddia eden var mı?
David Mulder

Ödül TrungDQ (uzunluğundan bağımsız olarak sadece bir kod perspektifinden (sadece düğümümüzden daha iyi) daha iyi) şaşırtıcı olduğunu düşünüyorum, bunu vermeden önce 24 saat beklemek zorunda.
David Mulder

Yanıtlar:


14

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

C'de bir logişlevin yalnızca belirli bir tür için tanımlanabileceğini unutmayın. Bu nedenle, bu log"işlev" yalnızca intbağımsız değişkenleri alır .

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

Daha genel bir çözüm, argümanın kendisine ek olarak argümanın nasıl yazdırılacağını belirtir:

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

bu örneğin olarak kullanılacaktır lg2("%s", "I'm a string");ya da lg2("%f", 3.1415).


Etraftaki son parantezlerin xgerekli olduğunu sanmıyorum .
user12205

@ace: Kullanıcı bağımsız değişkene bazı garip karakterler koyarsa bunlara ihtiyaç duyulabileceğini düşündüm, ancak yansıma üzerine haklı olduğunu düşünüyorum. Onları kaldıracağım.
nneonneo

10

Python (% 65-10 = 58.5)

Bu, kodunuzun bir dosyada olduğunu varsayar (etkileşimli yorumlayıcıda çağrılırsa tek çıktı üretir):

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

Python 2.7.6 üzerinde test edilmiştir.

Misal:

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

log(foo())

çıktılar

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
Güzel! Söylemeliyim ki, bu beni bir programcı olarak ilgilendiren çılgınca şeyler (yerel bir işlevin olumsuz endeksi: O): P bazı dokümanlar bulmak için harikalar yaratıyor
David Mulder

9

C ++ 121 71 67-10% = 60.3

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

Bunun gibi kullanılır:

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

Çıktılar:

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

30 karakterini kaldırabilir ve C ++ yerine C'ye yazarsanız tek satırlık yapabilirsiniz: #define log(x)printf("log(%s) %d\n",#x,x)ancak bu yalnızca tamsayılarla çalışır.
user12205

@ace: o zaman sadece bir tür için çalışır. (Ayrıca, bu önerdiğim çözümdür, aşağıya bakın)
nneonneo

@nneonneo Yorum göndermeden önce yenilemeyi unuttuğumda nefret ediyorum.
user12205

5

Rebol3 - 31,5 (% 35-10)

Sayılar için iyi çalışan @draegtun'dan kısaltılmış basit bir uygulama:

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

Çalıştırma çıktıları:

>> 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 karakterde (% 47 - 10) çok daha esnek olabilir (sayı olmayan türlerin biçimini görüntülemek için )

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

Çıktı:

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

Bu logaradığınız işlev olduğunu düşünüyorum :

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

kullanım

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

Çıktı

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

Uzun kod

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

Yalnızca komut dosyası belgeye <script>konulan etiketin içine konulduğunda çalışır, .htmlçünkü location.hrefkaynak kodunu almak için bir istek gönderir . JSfiddle, F12 Dev Araç Konsolu, gömülü.js dosyaları çalışmaz, her yerde kullanılabilir hale getirmeye çalışıyorum ...

Her neyse, bu soru ilginç.


Biraz şüpheliyim, bu çapraz tarayıcılar.
Farid Nouri Neshat

3

Scala - (221-10%) = 198.9

Yay makroları! Bu aslında tam da böyle bir şey.

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

Okunabilir sürüm:

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

Misal:

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

Çıktılar:

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

Ekleme Scala'da bir yöntem çağrısı olduğundan, bu sözdizimini tekrar ekler, ancak oldukça yakın! Diğer birkaç durumda da biraz daha ayrıntılı.


Vay canına, bu fonksiyonun eklenmesini görmek oldukça ilginç. Öğrenmek için çok güzel şeyler: D
David Mulder

2

bash (% 21 - 10 = 18,9)

Bu:

alias log=echo;set -v

O zaman kullanacağınız loggibi kullanın echo:

log $((1+1))

veya

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

Bu yöntem gerekli olan her şeyi yapacaktır; bonus olarak, bazı ekstra bilgiler de yazdırılır, ancak açık bir kural bunu yasaklamaz.


2

BASH

Bağımsız değişkenler BASH'de "(...)" kullanılarak geçirilmez, bu yüzden 'log ()' çıktısının şu stile uymasına izin veririm:

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

$((...))$[...]bunun yerine olabilir ama karakter saymadım, bu yüzden şimdiye kadar önemli değil.

2

Clojure

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

Homoiconicity'nin faydaları var!

Kullanmak:

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

Bakalım neler oluyor 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__))

Alıntı xyaparsanız, gerçekten bir ara gensim (yani. x#) Kullanmanız gerekir mi? İfadeyi yalnızca bir kez değerlendireceğinizi düşünüyorum (btw, Clojure uzmanı değilim)
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

Alternatif olarak, ancak kuralları karşılamıyor

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}

Kullanımı:

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

Düzenleme : küçük gelişme


0

Ortak 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)))))
  • Adını @çünkü logstandart logaritma fonksiyonu ve (en azından SBCL üzerine) varsayılan olarak kilitlenir. Ayrıca,@ sadece bir karakter uzunluğundadır.
  • prognDeğişken sayıda bağımsız değişken alarak a olarak işlev görür , ancak standart çıktıya yazdırır. Gerçek uygulamalarda, muhtemelensignal boşlukla ayrılmış çıktıyı basmak yerine S ifadesi olan bir koşul .
  • Mevcut Clojure çözümünün aksine, sonuçta günlüğe kaydedilen ifadenin değerini döndürüyoruz, böylece (@ x)her zaman kullanılabilirx kullanıldığında kullanılabilir.
  • Yazdırma prin1,read -able dize . Bu, günlüğe kaydedilen ifadeleri yeniden oluşturmaya çalışırken faydalıdır.
  • Tüm olası türleri işler (C cevabına bakınız)
  • Çoklu değerleri dikkate alır
  • Farklı çıktılar üretmez (bkz. Scala cevabı)
  • Bir dosyadan ve REPL'den çalışır (Bkz. Pyhton cevabı)
  • Tarayıcı / yorumlayıcı hile gerektirmez (Python traceback, Javascript isteği)

Örnek çıktılar:

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

Ve son olarak, yukarıdakileri defmacrokaydedersem, çözülmemiş versiyona sahibim:

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

Bunun yerine logkullandığım başka bir modül ( APD) kullanmadan PHP yeniden ilan loggedemez, loggerekirse gerekirse örnek ile yeniden gönderebilirsiniz . Bu küçük, ama daha günahkâr sanırım bu günlük fonksiyonu tek başına bir çizgi üzerinde olduğunu varsayalım. Cevabımı yorumların gerektirdiği şekilde güncelleyebilirim.

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

örnek çıktı:

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

Kullanımı:

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

Çıktı:

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

Çift tırnak kullanmalısınız ZORUNLU "yoksa işe yaramaz.


Verdiğim örnek sahte kodu izlemeyerek kuralları zaten bükmeksizin, daha büyük sorun, yalnızca değişkenlerin küresel bağlamda tanımlanması durumunda işe yarar ( yalnızca değerlendirme değerlendirme bağlamının bundan daha karmaşık olduğunu biliyorum, ama nokta duruyor)
David Mulder

Meydan okuma noktası bir ip
geçmemek oldu

Nokta yapmıyordu log("i:", i)... Ben js olmadan 'veya "js içinde yapılamaz sanmıyorum ... kullanarak daha küçük yapabilirsiniz console.log('log('+o+')'+eval(x))ama çıktı kod satır (kimin umurunda) maç olmaz
rafaelcastrocouto

2
Tek bir satırda yapabilirsiniz, düğümde yaptım, nasıl? Bir hata atarak, yığını alarak, dosyayı okuyarak ve satırı çıkararak. Evet, biraz çılgınca: D. Ek olarak kullanmak mümkün olabilir arguments.callee.caller.toString(), ancak iki günlük olduğunda hangi satırın hangisi olduğunu anlayamadım.
David Mulder
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.