import typing as tp
class Test:
@tp.overload
def __init__(self, x: int, y: str):
... # тут не должно быть тела!
@tp.overload
def __init__(self, other: 'Test'):
... # typehint в виде строки, так как класс Test еще не создан. Тела нет!
def __init__(self, *args, **kwargs): # настоящий конструктор
# определяем, как нас вызвали
if 'other' in kwargs:
first_arg = kwargs['other']
x, y = first_arg.x, first_arg.y
elif 'x' in kwargs:
x, y = kwargs.get('x'), kwargs.get('y')
elif isinstance(args[0], Test):
x, y = args[0].x, args[0].y
else:
x, y = args[0:2]
self.x: int = x
self.y: str = y
def __repr__(self) -> str:
return f'Test(x={self.x!r}, y={self.y!r})'
# порядковая передача аргументов сработает
t1 = Test(1, 'foo')
t2 = Test(t1)
print(t1, t2)
# именованная передача аргументов сработает
t3 = Test(x=2, y='bar')
t4 = Test(other=t3)
print(t3, t4)
Test(3, y='baz') # а вот это сломается...
fn main() {
let funcs = {
// Можно использовать не FnOnce, а что-то другое. Например Fn или FnMut. Но в любом случае придётся использовать dyn, тк наша лямбда берёт что-то из окружающего контекста.
let mut funcs: Vec<Box<dyn FnOnce() -> usize>> = Vec::with_capacity(3);
for i in 0..3 {
let i_copy = i.clone(); // вообще clone() тут не нужен, тк usize реализует трейт Copy. Оставлено для примера
funcs.push(Box::new(move || i_copy));
}
funcs
};
for func in funcs {
let result = func();
println!("{result}");
}
}
#[derive(Copy, Clone, Debug)]
struct Something(usize);
impl Something {
fn value(&self) -> usize {
self.0
}
}
fn main() {
let items = {
let mut items = Vec::with_capacity(3);
for i in 0..3 {
items.push(Something(i));
}
items
};
for item in items {
let result = item.value();
println!("{result}");
}
}
Но в этом случае мне придется выполнить 2 запроса к базе данных
sudo tee /etc/tmpfiles.d/mglru.conf <<EOF
w- /sys/kernel/mm/lru_gen/enabled - - - - y
w- /sys/kernel/mm/lru_gen/min_ttl_ms - - - - 1000
EOF
#include <iostream>
using namespace std;
int main() {
cout << "2 << 1 == " << (0b010 << 1); // 0b100
return 0;
}
#include <iostream>
using namespace std;
struct Foo {
Foo& operator<<(int x) {
cout << "Integer: " << x << '\n';
return *this;
}
Foo& operator<<(const char* str) {
cout << "String: " << str << '\n';
return *this;
}
};
int main() {
Foo foo;
foo << 3; // Integer: 3
foo.operator<<("Hello world"); // String: Hello world
return 0;
}
IL_0000: ldarg 1 // кладёт в стек первый аргумент
IL_0001: ldarg 2 // кладёт в стек второй аргумент
IL_0002: sub // достаёт из стека два последних значения и отнимает последний от пред последнего (т.е. будет arg.2 - arg.1), результат складывается в стек
IL_0003: brtrue.s IL_0011 // достаёт из стека значение, если оно не 0, переходит к инструкции IL_0011, если 0 исполнения идёт дальше на I_0005
IL_0005: ldstr "zero" // загружает в стек строку "zero"
IL_000a: call void System.Console::WriteLine(string) // вызывает вывод в консоль, из стека достаются N нужных значений для параметров (в данном случае 1), void функция ничего в стек не добавляет
IL_000f: br.s IL_001b // переход (jump) к IL_001b
IL_0011: ldstr "not zero" // загружает в стек строку "not zero"
IL_0016: call void System.Console::WriteLine(string) // вызывает вывод в консоль, из стека достаётся 1 значения для параметра
IL_001b: ldstr "done" // загружает в стек строку ...
IL_0020: call void System.Console::WriteLine(string) // ...
#include <stdio.h>
enum Opcode {
OP_LOAD_ARGUMENT,
OP_LOAD_STRING,
OP_SUBTRACT,
OP_GOTO,
OP_GOTO_IF_TRUE,
OP_CALL,
OP_RETURN
};
union Argument {
int value;
const void* pointer;
};
struct Instruction {
Opcode opcode;
Argument arg;
};
void run_vm(const Instruction* instructions, const Argument* args) {
Argument stack[16];
Argument* stack_pointer = &stack[0];
int address = 0;
while(true) {
const Instruction instruction = instructions[address];
address++;
switch(instruction.opcode) {
case OP_RETURN:
return;
case OP_LOAD_ARGUMENT:
*stack_pointer = args[instruction.arg.value];
stack_pointer++;
break;
case OP_LOAD_STRING:
*stack_pointer = instruction.arg;
stack_pointer++;
break;
case OP_SUBTRACT:
{
stack_pointer--;
int b = stack_pointer->value;
stack_pointer--;
int a = stack_pointer->value;
stack_pointer->value = a - b;
stack_pointer++;
break;
}
case OP_GOTO:
address = instruction.arg.value;
break;
case OP_GOTO_IF_TRUE:
stack_pointer--;
if(stack_pointer->value != 0)
address = instruction.arg.value;
break;
case OP_CALL:
void (* fn)(const void*) = (void (*)(const void*))instruction.arg.pointer;
stack_pointer--;
fn(stack_pointer->pointer);
break;
}
}
}
void print(const char* text) { printf("%s\n", text); }
int main(int argc, char** argv) {
const Instruction instructions[] = {
/* 0 */ { OP_LOAD_ARGUMENT, { 0 } },
/* 1 */ { OP_LOAD_ARGUMENT, { 1 } },
/* 2 */ { OP_SUBTRACT, {} },
/* 3 */ { OP_GOTO_IF_TRUE, { 0x7 } },
/* 4 */ { OP_LOAD_STRING, { .pointer = "zero" } },
/* 5 */ { OP_CALL, { .pointer = (void*)&print } }, // функции надо где-то регистрировать, чтобы знать сколько у них параметров и какого они типа
/* 6 */ { OP_GOTO, { 0x9 } },
/* 7 */ { OP_LOAD_STRING, { .pointer = "not zero" } },
/* 8 */ { OP_CALL, { .pointer = (void*)&print } },
/* 9 */ { OP_LOAD_STRING, { .pointer = "done" } },
/* A */ { OP_CALL, { .pointer = (void*)&print } },
/* B */ { OP_RETURN, {} }
};
const Argument args[] = {
{ 100500 },
{ 777 }
};
run_vm(instructions, args);
return 0;
}
use std::env::current_exe;
fn main() {
let x = current_exe();
println!("{x:?}")
}
What is an early return?https://dev.to/jpswade/return-early-12o5
An early return, or “return early” is an approach to keep readability in functions and methods.
It is always considered a wise choice to return early if simple conditions apply that can be checked at the beginning of a method.
Что такое Docker простыми словами
простыми словами