Страницы

Поиск по вопросам

понедельник, 17 июня 2019 г.

Вывод lambda функции, в виде текста

Приветствую! Знатоки выручайте, долгое время уже пытаюсь разобраться с этим вопросом и никак не могу найти информацию, а точнее нашел, но не то. Вообщем сама задача.
Есть массив, который содержит в себе lambda функции:
$functs = ['name' => function() { return 1; }];
Мне нужно создать для него редактирование, казалось бы все так просто, взять циклом пробежаться и всунуть все в input и textarea поля.
Но возникла проблема сами функции они не выводятся так как нужно. А нужно чтобы они также выводились как определены в массиве, то есть строкой.
function() { return 1; }
Прям точно также - как и определены в значении массива. Пробовал делать так:
$func= new ReflectionFunction($functs['name']); var_dump($func->__toString());
Но! Выводится мусор, не то, что нужно:
Closure [ function {closure} ] { @@ .....\index.php 11 - 13 }
Уже какой день бьюсь в этом направлении и никак не могу решить задачу, чтобы было ключ массива в input, а значение в textarea. То есть вот так:
Пожалуйста помогите или пните в правильном направлении.
UPD: Массив может быть любого вида: Хоть такой:
$functs = ['name' => function() {return 1;},'m'=>fucntion() {}];
В одну строку.
Пробовал решить так:
function closure(Closure $closure) { $function = new ReflectionFunction($closure); $file = file($function->getFileName()); for ($i = $function->getStartLine() - 1; $i < $function->getEndLine(); $i++) { $str .= $file[$i]; } $funct = mb_substr($str, mb_stripos($str, 'function', 0, 'utf-8'), -1, 'utf-8'); $funct = mb_substr($funct, 0, mb_strripos($funct, '}', 0, 'utf-8')+1, 'utf-8'); return $funct; }
Работает, но только если размер массива 1. То есть такой:
$functs = ['name' => function() {return 1;}];
а в случае: (new MyClosure($closure))->__toString(); возникает LogicException, что не совсем гуд, исключено, чтобы это было. нужно решение, чтобы в любом написании массива с lambda функциями. Кстате, ссылка с приведенным алгоритмом, не пашет тоже.
Незнаю, как поправить свою функцию, так, чтобы отследить правильную позицию завершения блока функции " } ", а не искать конец " } ", а то получается, что он захватывает все и получается хрень. Похоже и длину строки надо считать и т.д., формула нужна, как верно отследить. Выручайте, не врублюсь, какое условие написать?


Ответ

Пришлось делать запись данных уже в нужном виде (если посоветуете, что-то, лучше, буду рад):
public final function arrayDump(array $array): string { if (1 <= sizeof($array)) { $arr = []; foreach ($array as $key => $value) { $key = addslashes($key); if (is_callable($value)) { $value = $this->closure($value); $arr[] = "'{$key}' => {$value}"; } else if (is_string($value)) { $arr[] = "'{$key}' => '" . addslashes($value) . "'"; } else if (is_float($value) || is_double($value)) { $value = (double) $value; $arr[] = "'{$key}' => {$value}"; } else if (is_int($value)) { $value = (int) $value; $arr[] = "'{$key}' => {$value}"; } else if (is_object($value)) { $arr[] = "'{$key}' => '" . serialize($value) . "'"; } } return"[
\t" . join("\t", $arr) . "
];"; } return''; }
Ну и сам метод closure
public final function closure(Closure $closure): string { $func = 'function('; $function = new ReflectionFunction($closure); $params = []; $parameters = $function->getParameters(); foreach ($parameters as $param) { $string = ''; if ($param->isArray()) { $string .= 'array '; } else if ($param->getClass()) { $string .= $param->getClass()->name . ' '; } if ($param->isPassedByReference()) { $string .= '&'; } $string .= '$' . $param->name; if ($param->isOptional()) { $string .= ' = ' . var_export($param->getDefaultValue(), true); } $params[] = $string; } unset($parameters, $param); $func .= join(', ', $params) . ') {' . PHP_EOL; $lines = file($function->getFileName()); $start = $function->getStartLine(); $end = $function->getEndLine(); for ($l = $start; $l < $end; ++$l) { $func .= $lines[$l]; } return $func; }
Теперь нормально работает.

Фрагменты наслаиваются друг на друга. [дубликат]

На данный вопрос уже ответили: Наложение фрагмента на фрагмент. За добавленным фрагментом виден предыдущий 2 ответа @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); layoutForFragment = (FrameLayout) findViewById(R.id.layout_for_fragment); fragmentTransaction = getFragmentManager().beginTransaction(); fragmentTransaction.add(R.id.layout_for_fragment,cardStation);
fragmentTransaction.commit(); }
В методе OnCreate я вставляю фрагмент во FrameLayout. Проблема в том, что при повороте экрана или при вылете с ошибкой фрагменты накладываются друг на друга на одно и то же место. Как решить проблему ?


Ответ

При повороте экрана активити пересоздаётся. При пересоздании активити система пытается восстановить предыдущее состояние. В предыдущем состоянии в активити добавлен фрагмент и система его восстанавливает, добавляя на экран. После этого выполняется onCreate, где вы добавляете ещё один фрагмент. Итого их у вас (число поворотов экрана)*1
Вам надо просто проверять восстановила ли активити к-л фрагмент, поискав его во FragmentManager по ID контейнера, и, если нет, то добавлять его:
cardStation = getSupportFragmentManager().findFragmentById(R.id.layout_for_fragment); if (cardStation == null) { cardStation = new CardStation(); getSupportFragmentManager(). beginTransaction().add(R.id.layout_for_fragment, cardStation) .commit(); }

Как отправить изменения из текущей ветки в новую ветку в удалённом репозитории?

Если выполнить команду git branch -a то она выводит вот такое
aleksey@aleksey:~/Downloads/NTZ/FittingRoom$ git branch -a * develop master remotes/origin/HEAD -> origin/master remotes/origin/master
2 ветки локальные и 2 на сервере... Локально master и develop , и теперь если я хочу сделать пуш на сервер, то мне обязательно нужно его делать в мастер... Но эта ветка у меня для релизов...
Как создать на сервере ветку дев?
ПРАВКА
$ git remote show origin * remote origin Fetch URL: https://gitlab.com/alekseytimoshchenko/NewTimeZone.git Push URL: https://gitlab.com/alekseytimoshchenko/NewTimeZone.git HEAD branch: master Remote branch: master tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date)


Ответ

$ git remote show origin ... Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date)
здесь видно, что для команды git pull (без параметров) сконфигурирована только локальная ветка master (будут забираться обновления из удалённой ветки master). аналогично и для git push (без параметров) — только обновления из локальной ветки master будут отправляться в удалённый репозиторий (в удалённую ветку master).

локальную ветку можно сконфигурировать на отправку изменений в любую ветку удалённого репозитория (при вызове git push без параметров в этой ветке).
проще всего это сделать, однократно передав команде git push опцию -u (--set-upstream). естественно, надо указать и имя репозитория и ветку в нём, к которой текущая ветка будет «привязана».
для вашего конкретного случая:
сделайте ветку develop текущей:
$ git checkout develop отправьте изменения из неё, одновременно указав «привязку» к удалённой ветке develop в репозитории origin (приведён и пример вывода):
$ git push -u origin develop Total 0 (delta 0), reused 0 (delta 0) To url-репозитория * [new branch] develop -> develop Branch develop set up to track remote branch develop from origin.
последняя строчка как раз и сообщает о том, что локальная ветка develop «связана» с удалённой веткой develop (в репозитории origin).

теперь команда:
$ git remote show origin
покажет чуть больше информации про «привязки»:
... Local branches configured for 'git pull': develop merges with remote develop master merges with remote master Local refs configured for 'git push': develop pushes to develop (up to date) master pushes to master (up to date)
и выполняемая в дальнейшем в ветке develop команда git push (без параметров) отправит изменения именно в удалённую ветку develop

к слову
разово отправить изменения из любой локальной ветки в (почти) любую ветку в удалённом репозитории (и не осуществляя никаких «привязок») можно так:
$ git push репозиторий локальная_ветка:удалённая_ветка
например, для вашего случая:
$ git push origin develop:develop
если ветка с указанным именем не существует в удалённом репозитории, она будет создана. а если существует, то, в принципе, команда может завершиться с ошибкой — если «влить» изменения из локальной ветки в удалённую не получится. но это уже совсем другая история.

Регистр имен файлов Windows и Mercurial

Есть такая проблема. Сайт разрабатывается под Windows, а сервер веб-сервисом крутится под Linux. Использую систему контроля версий mercurial.
Можно ли под Windows его как-нибудь настроить, чтобы изменение регистра имён файлов тоже считалось изменением файла (сделать регистрозависимым)?


Ответ

Из ртутного руководства, глава 7, параграф 7
(здесь речь идёт об исправлении проблем с регистром имён файлов. но понятно, что Mercurial просто не заточен на решение подобных вопросов, считает их как возможные конфликты, и вообще: система хранилищ Mercurial регистронезависима)
Если вы используете Windows или Mac в среде, где кто-то использует Linux или Unix, и Mercurial сообщает о проблемах с регистром, когда вы пытаетесь сделать hg update или hg merge, процедура исправления этого очень проста. Просто найдите ближайшую машину с Linux или Unix, клонируйте на нее репозиторий и используйте команду hg rename для изменения имени на какое-то другое, так чтобы конфликта не было. Сохраните свои изменения (hg commit), сделайте hg pull или hg push в ваш Windows или MacOS репозитарий и hg update на ревизию без конфликта. Список изменений с конфликтом регистра останется в истории вашего проекта и вы все еще будете не в состоянии выполнить hg update вашей рабочей директории к этому набору изменений в Windows или MacOS, но вы сможете продолжить разработку.

Сервлеты и многопоточность

Вопрос по данному коду :
1.Насколько я знаю Servlet Container отвечает за потокобезопасность сервлетов.
2.Но сушествует вариант что несмотря на это может возникнуть проблема с потокобезопасностью как например в данном коде.
Мой вопрос заключается в том: почему при данном коде переменная counter считается не потокобезопасной ?
package threadSafety; import java.io.IOException; import javax.servlet.*; import javax.servlet.http.*; import java.math.*; public class SimpleServlet extends HttpServlet { //A variable that is NOT thread-safe! private int counter = 0; public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().println(""); resp.getWriter().println(this + ":
"); for (int c = 0; c < 10; c++) { resp.getWriter().println("Counter = " + counter + "
"); try { Thread.currentThread().sleep((long) Math.random() * 1000); counter++; } catch (InterruptedException exc) { } } resp.getWriter().println(""); } }


Ответ

Создание собственных потоков в контейнере сервлетов - не очень хорошая практика. Если есть возможность, то лучше перейти к асинхронной обработки запросов
В противном случае, вы сами обязаны отвечать за потокобезопасность, отключение и вообще весь контроль за вашими потоками.
Отвечая на ваши вопросы:
1.Насколько я знаю Servlet Container отвечает за потокобезопасность сервлетов.
Для порожденных вами потоков - нет.
2.Но сушествует вариант что несмотря на это может возникнуть проблема с потокобезопасностью как например в данном коде.
Так как переменная у вас уровня экземпляра, а контейнер создает на каждый сервлет только один экземпляр его класса(https://java.net/downloads/servlet-spec/Final/servlet-3_1-final.pdf - глава 2, параграф 2.2), то и эта переменная будет общая для всех запросов и соответственно модифицировать ее могут несколько запросов одновременно.

Использовать терминал с сессией через Ruby

Ruby дает выполнять команды •Nix терминала через System, Exec, Irb и тд, но у меня не получается сохранить сессию между командами. То есть я открываю консольное приложение в нем через, например, exec("./app"), но внутренние команды исполнить не могу, как сделал бы это через обычную сессию /bin/sh.
# ./app app> do_something
Вот этот do_something и "отпадывает".
Спасибо кто откликнется, может библиотеки знает по этой теме, всему рад.
UPD: То есть у меня есть ./app и внутри него мне надо исполнить ряд действий отлавливая вывод инфы и на ее основе слать команды дальше. А проблема, с которой я сталкиваюсь, это когда программа доходит до команды запуска приложения она перенаправляет меня в терминал и прерывается (ожидая завершения работы текущей программы), а мне нужно исполнить внутри открывшегося ./app еще команды.


Ответ

Читайте внимательнее документацию.
exec делает "немножко" не то, что вы ожидаете
Replaces the current process by running the given external command
...он замещает текущий процесс Ruby. То есть, на этой строчке ваша программа завершается, вместо неё ОС приклеивает процесс, который вы запустили.
Скорее всего, вам нужен модуль Open3 из стандартной библиотеки, а конкретно методы popen3 и/или popen2. Они запускают новый процесс, прицепив к его потокам стандартного IO подконтрольные Ruby потоки, а также создают отдельный Thread, который ждёт завершения процесса.
То, что вы вводили бы с клавиатуры, подавайте в полученный stdin нового процесса, и не забывайте читать его stdout и stderr, поскольку размер их буферов обычно ограничен, и их заполенность может повесить программу. В документации есть об этом детали.

написание скрипта в скрипте JS

имеется такой код:
"; newWin.document.write(html);
но он интерпретируется неправильно, находящийся в строке html расценивается браузером как закрывающий тэг первой строки, т.е. последний закрывающий script остается без пары, а на странице появляется '; newWin.document.write(html);
задача: открытие нового окна и вызов диалога печати. для меня очень странно что браузер часть значения строки воспринимает как html который необходимо интерпретировать.
может есть более лаконичные способы решения моей задачи?


Ответ

По правилам парсинга сначала находится завершающий тег , и только потом парсится содержимое скрипта. Поэтому для написания в строке внутри скрипта надо использовать конкатенацию строк или фиктивное экранирование.