Задать вопрос
cblp
@cblp
говорящий с машинами

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

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



Я начну.



При начальном n >= 0 цикл выполнится n раз, уменьшая n

while ( n --> 0 )<br>
{ use(n); }<br>




Словарь как сокращённый switch

result = {<br>
    1: 'I',<br>
    5: 'V',<br>
    10: 'X',<br>
}.get(input, 'default value')<br><br>
# некоторые доводят до<br>
['no', 'yes'][boolean_condition]<br>
# но это уже зло<br>




Двойное отрицание как приведение к bool

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




marklarius напомнил про старый добрый обмен значений тройным xor

a ^= b, b ^= a, a ^= b;<br>А Mezomish рассказал, что нельзя сокращать это до

a ^= b ^= a ^= b;<br>потому что значение переменной меняется дважды в пределах одного выражения.



Унарный «+» как приведение к числу для языков с «волшебным» автоматическим преобразованием чисел в строки и обратно (Perl, PHP, JavaScript)

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

Можно применять «+» и к другим сущностям (спасибо creage):

+ new Date() // миллисекунды с начала Эпохи<br>



Aquahawk показал минипаттерн — аналог return для блока кода

do {<br>
    ...<br>
    if (some condition) {<br>
        result = some_value;<br>
        break;<br>
    }<br>
    ...<br>
} while(false);<br>




OlegTar напомнил о замечательном свойстве логических операций во многих языках: правый аргумент не вычисляется, если по первому уже всё ясно. Таким образом, можно использовать and (&&) в качестве if, а or (||) вместо if not.

# остановится на первом неудачном шаге<br>
( doFirstStep() and<br>
  doSecondStep() == 'ok' and<br>
  doThirdStep() == 0 and<br>
  sendReport() )<br><br>
# знаменитая шутка любителей Perl<br>
use Perl or die();<br>


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

# значение по умолчанию<br>
x = x or -273;<br><br>
# первая непустая строка<br>
'Mr. ' + (firstname or lastname or nickname)<br>
  • Вопрос задан
  • 7441 просмотр
Подписаться 64 Оценить 3 комментария
Пригласить эксперта
Ответы на вопрос 15
@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».

Ну а если нужны именно булевые операции (или побитовые) — есть стандартные для Си &, | и ^.
Ответ написан
Комментировать
@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);
    }
}
Ответ написан
aspect
@aspect
Собирал тут уже один habrahabr.ru/company/intel/blog/108231/?#comment_3423796
Ответ написан
Комментировать
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);
}
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Похожие вопросы