Самостійні журнали


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! Я особисто вважаю, що ваше запитання досить пристойне, але зазвичай краще запустити ідеї питань через пісочницю, щоб вирішити неясності тощо, перш ніж люди почнуть працювати над відповідями.
Мартін Ендер

Thx і корисний @ sandbox, можливо, було б добре пояснити його використання help/on-topic(згадується, але я не вважав, що варто перевірити спосіб, який він там описав).
Девід Малдер

@ WolleVanillebärLutz: Звичайно, це не так, чи бачили ви, хто тоді стверджував, що це правда?
Девід Малдер

Бонус - це TrungDQ (я думаю, що його рішення є дивовижним лише з точки зору коду (краще, ніж наше рішення тільки для вузла), незалежно від довжини), доведеться почекати 24 години, хоча перш ніж я зможу його нагородити.
Девід Малдер

Відповіді:


14

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

Зауважте, що в С 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не потрібні.
користувач12205

@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

Ви можете видалити 30 знаків і зробити однолінійний, якщо ви запишете його на C замість C ++:, #define log(x)printf("log(%s) %d\n",#x,x)але це буде лише цілим числом.
користувач12205

@ace: тоді він працює лише для одного типу. (Також це рішення, яке я запропонував, див. Нижче)
nneonneo

@nneonneo Я ненавиджу це, коли забув оновитись, перш ніж публікувати коментар.
користувач12205

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>тегу, який вкладається в .htmlдокумент, оскільки він надсилає запит location.hrefна отримання вихідного коду. JSfiddle, F12 Dev Tool Console, вбудовані .jsфайли не працюватимуть, я намагаюся зробити його доступним скрізь ...

У будь-якому випадку це питання цікаве.


Я мало скептично налаштований на це крос-браузери.
Фарид Нурі Нешат

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

Оскільки додавання є викликом методу в Scala, він додає, що багатослівний синтаксис повертається, але він досить близький! Це також трохи більш багатослівно в декількох інших випадках.


Нічого собі, це досить цікаво побачити @ додавання функції. Стільки цікавих речей, щоб дізнатися: D
Девід Малдер,

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

Clojure

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

Лис звичайний - 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). Також @довжиною є лише один символ.
  • Діє як progn, приймаючи змінну кількість аргументів, але друкує до стандартного виводу. У реальних програмах я б, мабуть, signalумова із S-виразом замість друку виходу, розділеного простором.
  • На відміну від існуючого рішення Clojure, ми в кінцевому підсумку повертаємо значення зареєстрованого виразу, так що (@ x)його можна використовувати щоразу, коли xвикористовується.
  • Друк використовує prin1, що виводить readрядок -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

Ви не можете повторно декларувати logPHP, не використовуючи інший модуль ( APD), тому я використовував 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 складніший за це, але крапка стоїть)
Девід Малдер

Суть виклику полягала в тому, що ти не пройдеш струну ... -1
Doorknob

Справа не в тому log("i:", i)... Я не думаю, що це неможливо зробити без 'або "в js ... ви можете зробити його меншим за допомогою, console.log('log('+o+')'+eval(x))але вихід не буде відповідати рядку коду (кого це цікавить)
rafaelcastrocouto

2
Ви можете це зробити в одному рядку, я це робив у вузлі, як? Відкидаючи помилку, отримуючи стек, читаючи файл і витягуючи рядок. Так, начебто божевільний: D. Додатково це можливо за допомогою arguments.callee.caller.toString(), але я не зміг зрозуміти, який рядок є, коли у вас є два журнали.
Девід Малдер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.