Простой шаблонизатор, когда такие монстры как Twig избыточные
class Templater
{
/** @var array Данные для шаблона */
public $data = [];
/** @var string Путь к шаблону */
public $templatePath = "";
public function render()
{
ob_start();
ob_implicit_flush(false);
if ($this->data) {
extract($this->data);
}
// Не забывайте на самом верхнем уровне делать
// try {...} catch (\Exception $e) { echo ob_get_clean(); }
// и/или логгирование
require($this->templatePath);
return ob_get_clean();
}
}
var testObj2 = {
m2: 'm2Value'
}
var testObj = {
method1: function() { return testObj },
method2: function() { return testObj },
obj2: testObj2
}
//оригинальное значение
var testVal = may(testObj)
.pipe(function(item) { return 1 }) // переписали оригинальное значение
.pipe(function(item) { return item + 12 }) // добавили к 1 еще 12 итого 13
.pipe(function(item) { return item + 12 }) // по той же схеме, получаем 25
.value
console.log('test testObj.pipe() is 25 :=> ', testVal);
// допустим у нас есть функция которая при вызове вернет еще функцию и так 5 раз
var callbackHell = function() {
var l4 = function() { return 'done' };
var l3 = function() { return l4; };
var l2 = function() { return l3; };
var l1 = function() { return l2; };
return l1;
}
//передаем саму функцию не вызывая
var cbHellTest = may(callbackHell)
.run(function(item) { return item }) // вызов callbackHell()
.run(function(item) { return item }) // вызов l1()
.run(function(item) { return item }) // вызов l2()
.run(function(item) { return item }) // вызов l3()
.run(function(item) { return item }) // вызов l4() которая вернет нам "done"
.value;
console.log('test cbHellTest.run() is "done" :=> ', cbHellTest);
//так же вызовы можно комбинировать
var testCall = may(testObj)
.run(function(item) { return item.method1 }) // метод вернет testObj
.run(function(item) { return item.method2 }) // метод так же вернет testObj
.run(function(item) { return item.method3 }) // а такого метода нет, значит мы пропустим вызов
.pipe(function(item) { return item.obj2 }) // тут item это результат вызова item.method2()
.pipe(function(item) { return item.m2 }) // тут item равен результату из предыдущей цепочки
.value
//проверочные функции для наглядности
console.log('test testObj.run() is ', testObj2.m2, ' :=> ', testCall);
//если значение null или undefined то вернется значение переданное в or
console.log('test null.or(12) :=> ', may(null).or(12).value);
console.log('test 24.or(12) :=> ', may(24).or(12).value);
console.log('test 128.value :=> ', may(128).value);
// применить функцию переданную в map к значению
console.log('test 128.map(x => x * 2) :=> ', may(128).map(function(val) { return val*2 }).value);
// выполняет проверку значения на пустоту и кладет результат в value
console.log('test "undefined".empty() :=> ', may(void 0).empty().value);
// с этим результатом так же можно работать через pipe, or, map,
console.log('test "undefined".empty().pipe() is "undefined" :=> ', may(void 0).empty().pipe(function(val) { return val }).value);
function may(val) {
var value = val, tempValue = value,
empty = function (expr) { return typeof expr === 'undefined' || expr === null; },
or = function (oVal, nVal) { return empty(oVal) ? may(nVal) : self; },
self = {
value: tempValue,
or: or.bind(self, tempValue),
empty: function() { return empty(tempValue) ? may(true) : self; },
pipe: function (cb) { var cbVal = cb(tempValue), orMay = empty(cbVal) ? self : may(cbVal); tempValue = orMay.value; return orMay; },
run: function(f) { var mapMay = self.map(f(tempValue)); tempValue = mapMay.value; return mapMay; },
map: function (f) { return typeof(f) === "function" ? may(f(tempValue)) : self; }
};
return self;
}
Игра "Змейка" реализованная в исходном коде (Квайн). Для каждого следующего шага необходимо компилировать код и сохранять его в файл (пока только Windows):
Функция, преобразующая js-объекты в узлы DOM. Пример использования:
render(['p', {class: 'body'}, 'Search engines:',
['ol',
['li', ['a', {href: 'http://www.google.com'}, 'Google']],
['li', ['a', {href: 'http://yandex.ru'}, 'Yandex']]
]]);
Возвращает:
<p class="body">
Search engines:
<ol>
<li><a href="http://www.google.com">Google</a></li>
<li><a href="http://yandex.ru">Yandex</a></li>
</ol>
</p>
function render(spec) {
var elem, attr, attrs, child, n = 1;
if (!(spec instanceof Array))
return document.createTextNode(''+spec);
if (spec.length < 1)
return undefined;
elem = document.createElement(spec[0]), attrs = spec[1];
if (typeof(attrs) == "object" && !(attrs instanceof Array)) {
for (attr in attrs) if (attrs.hasOwnProperty(attr))
elem.setAttribute(attr, ''+attrs[attr]);
++n;
}
while (n < spec.length) {
child = render(spec[n++]);
child && elem.appendChild(child);
}
return elem;
}
Использование:
first = Sequence.new(1)
puts first #=> "1"
second = first.next
puts second #=> "11"
puts first.next.next #=> "21"
puts second.next.next #=> "1211"
class Sequence
def initialize(first_element)
@current_element = first_element.to_s
end
def to_s
current_element
end
def next
self.class.new(next_element)
end
private
attr_reader :current_element
def next_element
current_element.scan(/((\d)\2*)/)
.map { |element| "#{element.first.size}#{element.last}" }.join
end
end
Обмен значений двух числовых переменных без использования третьей. Носит характер занимательной задачки ;-)
function swap(&$a, &$b) {
$a = $a + $b;
$b = $a - $b;
$a = $a - $b;
}
usage
(function(){
ConstructName();
})();
(function(window){
function ConstructName(){
"use strict";
var $selectorsClass = {
dragHandle: '.drag-handler'
};
function handleModuleSortable(){ }
function handleModuleGridView(){ }
function init(){
handleModuleSortable();
handleModuleGridView();
}
init();
}
window.ConstructName = ConstructName;
})(window);
Pipeline собственно для лямбд. Для него здесь вместо |
использован /
.
Класс PV вообще можно использовать и для одного аргумента, но тогда на выходе у него будет массив с одним элементом соответвенно.
Код без проблем компилируется как в Java-классы так и в Javascript.
Пример использования:
P(1.0) / {it + 3} / {it - 2} / {it * 5} / {println(it)}
PV(1, 2, 3) / {it + 3} / {it - 2} / {it * 7} / {println(it)}
Реализация на Kotlin, который на момент публикации отсутствовал среди доступных языков.
Запустить можно здесь
Upd: еще немного упростил реализацию
// Pipeline with one argument
class P<A> (val v: A) {
inline fun <B> div(op: (A) -> B) = P(op(v))
}
// Pipeline with multiple arguments
class PV<A> (vararg val v: A) {
inline fun <reified B> div(op: (A) -> B) = PV(*array(v.map{op(it)}))
inline fun <reified T> array(col: List<T>) = Array<T>(col.size()){col[it]}
}
Этот код я использовал в первой своей статье на хабре. На текущий момент я написал три статьи, посвящённые вебсокет серверу на PHP. Весь код из статей оформлен в виде библиотеки и выложен github
#!/usr/bin/env php
<?php
$socket = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
if (!$socket) {
die("$errstr ($errno)\n");
}
while ($connect = stream_socket_accept($socket, -1)) {
fwrite($connect, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\nПривет");
fclose($connect);
}
fclose($socket);
Простая реализация менеджера событий.
<?
class EventManager {
$listeners = [];
public function register($eventName, $listener) {
$this->listeners[] = [
'eventName' => $eventName,
'listener' => $listener
];
}
public function fire($eventName, $data) {
foreach ($this->listeners as $listener) {
if ($listener['eventName'] == $eventName) {
call_user_func([$listener['listener'], $listener['eventName']], $data);
}
}
}
}