cblp
@cblp
говорящий с машинами

Какие кодотрюки вы знаете?

Какие красивые трюки и изящные приёмы, помогающие в написании кода, вы знаете? Только без фанатизма, давайте такие, на понимание которых требуется не больше секунды. Ну ладно, не больше пяти-десяти секунд в запущенных случаях.


Я начну.


При начальном n >= 0 цикл выполнится n раз, уменьшая n
while ( n --> 0 )
{ use(n); }



Словарь как сокращённый switch
result = {
    1: 'I',
    5: 'V',
    10: 'X',
}.get(input, 'default value')

# некоторые доводят до
['no', 'yes'][boolean_condition]
# но это уже зло



Двойное отрицание как приведение к bool
> [0, 1, !!0, !!1]
[ 0, 1, false, true ]
// полезность данного трюка спорная, по-моему, лучше явно приводить


marklarius напомнил про старый добрый обмен значений тройным xor
a ^= b, b ^= a, a ^= b;А Mezomish рассказал, что нельзя сокращать это до
a ^= b ^= a ^= b;потому что значение переменной меняется дважды в пределах одного выражения.


Унарный «+» как приведение к числу для языков с «волшебным» автоматическим преобразованием чисел в строки и обратно (Perl, PHP, JavaScript)
+"10" == 10Осторожно! Поведение оператора отличается от parseFloat и тем более от parseInt (JavaScript), следует использовать его только в тех случаях, когда вы ожидаете от аргумента только число, возможно, в строке, но всё остальное можно счесть за ошибку. Пример: +'1cm' == NaN, но parseFloat('1cm') == 1.

Можно применять «+» и к другим сущностям (спасибо creage):
+ new Date() // миллисекунды с начала Эпохи

Aquahawk показал минипаттерн — аналог return для блока кода
do {
    ...
    if (some condition) {
        result = some_value;
        break;
    }
    ...
} while(false);


OlegTar напомнил о замечательном свойстве логических операций во многих языках: правый аргумент не вычисляется, если по первому уже всё ясно. Таким образом, можно использовать and (&&) в качестве if, а or (||) вместо if not.
# остановится на первом неудачном шаге
( doFirstStep() and
  doSecondStep() == 'ok' and
  doThirdStep() == 0 and
  sendReport() )

# знаменитая шутка любителей Perl
use Perl or die();


Кроме того, в некоторых языках (Python, JavaScript) результирующее значение равно последнему вычисленному операнду.
# значение по умолчанию
x = x or -273;

# первая непустая строка
'Mr. ' + (firstname or lastname or nickname)
  • Вопрос задан
  • 6765 просмотров
Пригласить эксперта
Ответы на вопрос 16
@marklarius
Самый классный трюк это заставить программистов документировать их творчество ;)
Ответ написан
@Aquahawk
do { if (some condition){ some code; break; } if (some other condition){ some code; break; } } while(false);

аналог ретурна без функции
Ответ написан
roman_pro
@roman_pro
Для врЕменного исключения из компиляции больших кусков C++ кода (возможно содержащих многострочные /*...*/ комментарии) удобно пользоваться конструкцией препроцессора
#if 0
(...some_temporary_removed_code...)
#endif
Ответ написан
OlegTar
@OlegTar
программист .NET, Javascript, Perl
способ менять 0 на 1, 1 на 0
$x = 1 или 0
....
$x = 1 - $x;

— сортировка, когда нужно слово 'Total' переместить вниз, покажу напримере Javascript, но можно и в других языках, где можно задавать функцию сравнения, например, в Perl. Пример показывает, что можно всякие значения ставить принудительно вверх или вниз.
[1, 'total', 'abc', 'zzz'].sort(function (a, b) { 
    if (a == 'total') {
        return 1
    }; 
    if (b == 'total') {
        return -1
    }; 
    if (a < b) {
        return -1
    } 
    else if (a > b) {
        return 1
    }; 
    return 0
});

Результат:
[1, "abc", "zzz", "total"]

В Javascript и Perl, если первое число 0, пустая строка null (в Javascript), undef (в Перл)
то заменить её дефолтным значением:
var x = null;
var t = x || 5;
t;

5

Осторожно, если x = 0, то вернётся последнее выражение. (В Perl 5.10 есть оператор //, аналогичный конструкции defined $x? $x: 5;)
Ответ написан
@Silver_Clash
x = y — 0 + (z — 0); что бы гарантированно не получить конкатенацию :)
Ответ написан
Mrrl
@Mrrl
Заводчик кардиганов
Недавно придумал, как считать ненулевые биты в int:

res=0; while(a){ a&=a-1; res++;}

Потом оказалось, что в Hacker's Delight оно уже есть.
Ответ написан
JustAMan
@JustAMan
Сюда же интересная реализация or/and в Python:
def func(a, b):
    print a or b

func(None, 'q')
func(123, 10)
func([1,2,3],'')
func('', {1: 5})

выдаёт:
q
123
[1, 2, 3]
{1: 5}

т.е. результат казалось бы булевых выражений на самом деле совсем не булевый, а равен последнему вхождению, по которому прекратилась обработка условия. Так, «1 and 5» будет «5».

Ну а если нужны именно булевые операции (или побитовые) — есть стандартные для Си &, | и ^.
Ответ написан
@lagranzh
Я нахожу удобным использовать замыкания для эмуляции ОО. Вот пример на матлабе, но на другом языке где есть замыкания, все так же.

function [acc] = create_account(initial_value)
    value = initial_value;
    
    acc.total = @total;
    acc.add  = @add;

    function add(amount)
        value = value + amount;
    end

    function [res] = total()
      res  = value;
    end
end


теперь пользуемся
   a = create_account(0);
   a.add(1);
   a.add(5);
   x = a.total(); % x будет равен 6.


ПС: В матлабе есть объекты, но они какие-то не удобные.
Ответ написан
@Aquahawk
ещё в javascript можно делать что-то типа
obj ||= {}

это создаст объект если его нет, а если есть, то ничего с ним не сделает.
А ещё есть мегавзрыв мозга Duff's Device
strcpy(to, from, count)
register char *to, *from;
register count;
{
    register n = (count + 7) / 8;
    if (!count) return;
    switch (count % 8) {
    case 0: do { *to = *from++;
    case 7:      *to = *from++;
    case 6:      *to = *from++;
    case 5:      *to = *from++;
    case 4:      *to = *from++;
    case 3:      *to = *from++;
    case 2:      *to = *from++;
    case 1:      *to = *from++;
               } while (--n > 0);
    }
}
Ответ написан
silvansky
@silvansky
В Objective-C есть куча трюков с runtime: class_addMethod, к примеру.
Ответ написан
coffeesmoke
@coffeesmoke
Трюки с кодом — вещь забавная для самого программиста. Но если работаешь в команде или публикуешь исходники для всех, то на передний план необходимо выставить удобство чтения, как бы при этом не хотелось поумничать. Лучшее, что можно позволить — приведение указателей разного типа или memcpy(...). :)
Ответ написан
Небольшой трюк, как можно поменять местами две численные переменные, без использование третьей.

$a = 5;
$b = 7;
$a = $a + $b; // 12
$b = $a - $b; // 5
$a = $a - $b; // 7
Ответ написан
creage
@creage
JS:
проверка позиции вхождения
if (~index) { //did } else { //didn't find it }

миллисекунды с epoch
+ new Date()

ну и еще куча, по JS, на 140байтах.
Ответ написан
avn
@avn
Я вот чего в C/C++ люблю:
#define sizeofarr(ARR) (sizeof(ARR) / sizeof(ARR[0])) ... int arr[23534]; long f; for (f = 0; f < sizeofarr (arr); ++f) { ... }

И странно, что в стандарте такого нет
Ответ написан
@Sh0ttky
Завёл себе репозиторий, чтобы записывать туда сишные трюки.

https://sourceforge.net/p/c-is-freedom/code/ci/mas...

Сейчас там есть шаблоны на си в двух вариантах. Кстати более гибкие и понятные чем с++ шаблоны.
https://sourceforge.net/p/c-is-freedom/code/ci/mas...

Был бы очень рад, если кто-то предложит туда мерж со своими трюками.
( fork -> затем закоммитить в форк своё -> merge reguest )

Вот ещё трюк:
/* 
   USAGE: 
   int64_t m = supermax(1, 234234, 35423523, 777); // m = 35423523
*/

#include "stdint.h"
#include "limits.h"

#define NUM_OF_ARGS(...) (sizeof((int64_t[]){__VA_ARGS__})/sizeof(int64_t))

#define supermax(...) _supermax((int64_t[]){__VA_ARGS__}, NUM_OF_ARGS(__VA_ARGS__))
int64_t _supermax(int64_t arr[], int size)
{
    int64_t max = arr[0];

    int i = 0;
    while (i < size) {
        if (arr[i] > max)
            max = arr[i];
        i++;
    }
    return max;
}


#include "stdio.h"

int main()
{
    int64_t x = supermax(1,2,3,4,5);
    printf("%lld\n", x);
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы