Хочу рассказать про dap — интересный и необычный язык реактивных правил для написания, в частности, веб-фронтендов.
Для затравки простая задачка: взять список неких пользователей (воспользуемся тестовыми данными, любезно предоставляемыми сервисом jsonplaceholder.typicode.com) и вывести их имена обычным html-списком; при нажатии на имя пользователя — показать алерт с его id.
Это, конечно, легко делается и на React, и на Angular, и на Vue. Вопрос: насколько легко? В dap это делается так:
‘UL.users’.d(«* :query`https://jsonplaceholder.typicode.com/users» ,’LI’.d(«! .name»).ui(«? .id:alert») )
(*Этот и последующие dap-примеры можно интерактивно потестить в песочнице dap.js.org/test.html)
Это первая пришедшая в голову тривиальная задачка и тривиальный же способ ее решения. На dap удобно писать «в лоб», не городя огород из классов, компонентов и прочего ритуального реквизита. Что вижу, то пою. Но «пою» не на javascript или его производных, а на языке dap-правил, специально заточенном на простое и лаконичное описание реактивных зависимостей между элементами.
Карты глубин водоемов в смартфоне. Видео-инструкция к приложению Dap Drift Pro.
В примере выше, правда, никаких зависимостей пока нет. Зато есть:
- оператор * для итерации по данным,
- конвертер :query для асинхронной «конвертации» урла в полученные с него данные,
- оператор ! для «печати» в генерируемый элемент,
- конвертер alert , магически конверитрующий любые значения в алерт
Кстати: вы заметили, что этот пример написан на обычном javascript, а сами dap-правила это просто строки? И сигнатуры элементов («теги») — тоже строки, просто в одинарных кавычках. Да, код dap-приложения выглядит непривычно, но это — чистый javascript, готовый к употреблению: его не нужно транспилировать из исходников на новомодных языках (что, конечно, не помешает вам этими модными языками пользоваться при желании).
Чуть усложним задачку, добавив зависимостей: пусть при нажатии на имя пользователя его id и name отображаются крупненько в элементе H2, под ними пусть будет имейл, а также все его «посты», которые берутся из /posts?userId= .
Здесь уже имеем зависимость содержимого элемента ‘details’ (что в переводе н HTML означает ) от того, какой пользователь выбран. Выбранный пользователь, таким образом, оказывается переменной состояния. Такие переменные в dap-правилах обозначаются префиксом $ (как s в «state»). При нажатии на любой из элементов LI изменяется содержимое переменной $user , на что элемент ‘details’ автоматически реагирует и обновляется.
В dap структура программы определяет сразу и модель состояния и модель взаимодействия с пользователем (отображение и реакции). С одной стороны это позволяет писать красивый, лаконичный и понятный код, но с другой стороны — требует четкой иерархической структуры приложения. Лично я считаю это требование полезным ограничением: оно заставляет (и помогает) более тщательно прорабатывать логику приложения и избавляться от логических нестыковок.
DAP | Условия поставки товара | Инкотермс 2010
Каким образом ‘details’ узнает, что надо бы обновиться? Очень просто: в его правиле генерации присутствует обращение к переменной $user , а в правиле реакции элемента LI эта переменная как раз и изменяется.
Правила генерации — те, которые указываются с помощью метода .d — исполняются на фазе построения элемента. Правила реакции задаются методом .ui и исполняются при взаимодействии пользователя с элементом. Это два самых часто употребимых типа правил; кроме них есть еще несколько типов, но о них как-нибудь потом.
Синтаксис dap-правил довольно специфичен. Он не имеет ничего общего с всем привычным C-подобным синтаксисом, поэтому поначалу может казаться странным и непонятным. Но на самом деле он исключительно прост и, не побоюсь этого слова, прекрасен.
- ! — вывод значения в элемент, что-то вроде print
- !! — установка свойства (атрибута) элемента, что-то вроде setAttribute
- ? — условный оператор, что-то вроде if
- * — мультиплексор, или итератор, что-то вроде for
А кто не сталкивался с ситуацией, когда сидишь и тупишь, придумывая имя для переменной? Хотите верьте, хотите нет, в моем dap-коде практически все «булевы» (да/нет) переменные именуются $? (где $ — это префикс переменной состояния, а собственно имя состоит просто из знака вопроса). Мне просто лень придумывать им имена, а потом еще и печатать их в нескольких местах. При этом никогда не возникает никаких сложностей с пониманием, что эта переменная означает в каждом конкретном месте: благодаря компактности и обозримости dap-кода, вся область действия такой переменной обычно умещается в несколько строк, и всегда понятно что к чему.
‘toggle’.d(«$?=» // определяем $? и инициируем ее ‘ничем’ (удобная разновидность false) ,’BUTTON’.d(«! `Toggle»).ui(«$?=$. «) // кнопкой инвертируем $?, как в x=!x ,’on’.d(«? $?; ! `✓») // показать галочку если $? не пустой )
Разумеется, это всего лишь мой личный стиль. Если вы пришли из мира Enterprise Java, не беспокойтесь: никто не запретит вам использовать сколь угодно длинные идентификаторы в любом месте. Чего нельзя сказать о литералах.
Литералы в dap-правилах обозначаются префиксом ` (backtick, на клавиатурах обычно под клавишей Esc). Например, элемент BUTTON в примере выше подписан литералом `Toggle . В отличие от других, «нормальных» языков, где, скажем, строковые литералы заключаются в кавычки и могут содержать приличные объемы текста, в dap-правилах литералы обрамляются только с одной стороны (тем самым префиксом ` ), и не могут содержать пробелов, т.к. пробел служит разделителем токенов («аргументов») в правиле. Как же так, спросите вы? А вот так. Литералы в dap предназначены не для эпистолярных фрагментов, а для различных коротких кодов: номеров, меток, каких-то отладочных заглушек и.п. Текстовые данные (как, впрочем, и любые другие) dap настойчиво требует хранить в виде констант в специальном словаре, в секции .DICT (от «dictionary», понятное дело):
‘whoami’.d(«$fruit=» ,’H3′.d(«! ($fruit msg.fruit-selected msg.please-select)?! $fruit») ,’UL’.d(«* fruit» ,’LI’.d(«! .fruit»).ui(«$fruit=.») ) ) .DICT(< msg :< «please-select»: «Кто я? Зачем я в этом мире?», «fruit-selected»: «Я — » >, fruit :[«Апельсинчик, сочный витаминчик», «Яблочко зеленое, солнцем напоённое», «Cлива лиловая, спелая, садовая», «Абрикос, на юге рос»] >)
Очевидным преимуществом хранения всех текстов в словаре является, например, легкость последующих локализаций на другие языки.
Но в словаре хранятся не только текстовые данные, а вообще любые повторно используемые сущности. В том числе, параметризуемые шаблоны, или «компоненты», как их называют в других фреймворках:
В принципе, ничто не мешает вообще все приложение разбить на «компоненты» и запихнуть в словарь, если вам нравится такой стиль:
‘main’.d(«! header content footer») .DICT(< header : ‘HEADER’.d(. ), content : ‘UL.menu’.d(. ), footer : ‘FOOTER’.d(. ) >)
Лично я в этом смысла особого не вижу, и обычно выношу в словарь только те фрагменты, которые реально используются многократно.
Кстати, поскольку это все еще обычный javascript, а собственно словарь — это, как можно видеть, просто объект (или, как их еще называют, ассоциативный массив), то и формировать его можно любым легальным для javascript способом. Например, в примере чуть выше массив значений для константы colors генерируется из строки с помощью метода split. Можно вообще весь объект для словаря импортировать из внешнего скрипта-библиотеки любым доступным способом — хоть по старинке через или XHR->eval(), хоть через import (но убедитесь, что ваши клиенты этот новомодный способ поддерживают). Секций .DICT может быть несколько, все они объединяются в один общий словарь.
const lib1=< message: «Hello from lib1» >, lib2=< message: «Hi from lib2» >; ‘my-app’.d(«! message wrapped.message imported.message») .DICT(lib1) .DICT(< wrapped: lib2, imported: import «extern.js»; >) //файл extern.js (< message: «Bonjour de lib importé» >)
Помимо штатных средств javascript, для подключения внешних библиотек в dap имеется и свой механизм. Отличие его в том, что библиотеки подгружаются лениво — только тогда, когда действительно нужно что-то из библиотеки взять. Такие библиотеки указываются в секции .USES
‘main’.d(«$?=» // unset $? ,’BUTTON.toggle’.ui(«$?=$. «) // toggle $? ,’activated’.d(«? $?» // only show when $? is set ,’imported’.d(«! delayed.message») // now print the message from the lib ) ) .USES(< delayed: «extern.js» >)
Здесь библиотека extern.js загрузится только после нажатия кнопки, когда потребуется отобразить элемент ‘imported’ — а для этого распарсить и скомпилировать его dap-правило, которое и ссылается на внешнюю библиотеку.
Да, dap-правила «компилируются» перед исполнением. Причем лениво, только при первом фактическом обращении к шаблону элемента. Эта ленивость позволяет «размазать» компиляцию большого приложения на множество мелких этапов, и не занимать ресурсы браузера неиспользуемыми участками кода.
Конечно, актуальна такая забота о ресурсах только для каких-то совсем уж больших приложений, или слабых устройств. В целом могу сказать, что dap молниеносен (в масштабах UI, конечно) — и в компиляции, и в исполнении. Производительность можно контролировать в консоли браузера: там логируется время каждой реакции.
Единственные заметные задержки, которые реально могут возникать — это задержки сети. Но и эти задержки не блокируют dap-приложение. Веб-запросы, исполняемые конвертором :query асинхронны и не задерживают отображение и работу остальных элементов.
Кстати, что такое конвертор? Конвертор в dap — это просто функция вида value → value, то есть с одним входом и одним выходом. Такое ограничение позволяет строить из конверторов цепочки, например выражение $a:x,y,z соответсвует z(y(x($a))) в си-подобной записи. То, что вход у конвертора всего один, казалось бы, ограничивает его возможности по сравнению с «обычной» функцией. Но это не так.
Конвертор может принимать и отдавать как элементарные значения, так и объекты/массивы (в javascript разница между этими понятиями размыта), содержащие любое количество данных. Таким образом, конверторы в dap полностью заменяют «традиционные» функции, при этом могут собираться в цепочки и могут быть асинхронными, не требуя при этом никакого дополнительного синтаксического оформления.
Традиционных «функций» с фиксированным списком параметров в dap, соответственно, нет — за ненадобностью.
Зато есть еще агрегаторы — функции от произвольного числа аргументов (обычно равноправных, но не всегда). Например, агрегатор ()? возвращает первый непустой аргумент или самый последний (аналог ||-цепочки в javascript), а агрегатор ()! — наоборот, первый пустой аргумент, или самый последний (аналог -цепочки в javascript). Или, например, агрегатор ()uri — строит из аргументов параметризованный URI.
И последний тип функций в dap — это операторы. Если конверторы и агрегаторы идеологически ближе к «чистым» функциям, которые просто вычисляют значения (хоть и не всегда это так), то задача операторов — применять эти значения к генерируемому элементу (например, оператор ! добавляет значение аргумента к содержимому элемента, а оператор !! устанавливает атрибуты элемента) или управлять ходом исполнения правила (как, например, условный оператор ? )
Арсенал штатных конверторов, агрегаторов и операторов в dap минимален, но это не важно. Главное, что вы можете создавать свои! Это важный момент. Нужно четко понимать, что сам язык dap-правил вовсе не претендует на роль универсального языка программирования, он только описывает зависимости между элементами. Подразумевается, что хардкор и вычисления реализуются нативными средствами среды (для браузера, это, понятно, javascript) а dap играет сугубо «логистическую» роль — указывая, что, когда и из чего нужно делать и куда отдавать.
Собственный функционал описывается в секции .FUNC (от «functionality»):
‘UL.users’.d(«* :query`https://jsonplaceholder.typicode.com/users» ,’LI’.d(«! (.name .username:allcaps .address.city):aka,allcaps») .ui(«(.address.street .address.suite .address.city .address.zipcode)lines:alert») ) .DICT(< «no-contact»: «No contacts available for this person» >) .FUNC( < convert: < allcaps: o=>o.toUpperCase(), aka : o => o.name + » also known as «+o.username+» from the city of «+o.city >, flatten:< lines : values=>»Address:n» + values.reverse().join(«n») > >)
Здесь собственный функционал тривиален, поэтому написан непосредственно «по месту». Разумеется, что-то более сложное имеет смысл писать самостоятельным модулем, а в .FUNC прописывать только протокол взаимодействия между этим модулем и dap. Скажем, в примере с игрой в крестики-нолики dap.js.org/samples/tictactoe.html (по мотивам React-туториала), вся логика игры описана в отдельном замыкании, а dap только связывает эту логику с картинкой на экране.
Подробнее познакомиться с dap можно на сайте dap.js.org
Да, вот еще что. В сжатом виде весь dap-движок (
) весит ни много ни мало 9 кБ. Девять килобайт.
Источник: habr.com
Download Accelerator Plus
DAP — быстрый ускоритель и самый популярный менеджер закачек с более чем 265 миллионами установок по всему миру. DAP ускоряет загрузку до 600% быстрее, так что вы быстро получите то, что вам нужно. Видео, программы, фотографии и музыкальные файлы доставляются к вам на самых высоких скоростях на планете.
Download Accelerator Plus предоставляет возможность управления файлами, которые можно скачать быстро и без ожидания. Используя передовые технологии, программа позволяет скачивать файлы на более высоком уровне скорости и эффективности.
Программа обеспечивает вашу конфиденциальность и безопасность в Интернете совместно с инновационными технологиями скачивания DAP.
Загрузчик использует SPEEDbit Anti-Virus (МАВ) технологию, которая позволяет получать уведомления об угрозах из самых популярных антивирусных программ, таким образом давая вам возможность при открытии загруженного файла — защитить ваш компьютер от вредоносных программ и вирусов.
Download Accelerator Plus поддерживает 42 языка благодаря помощи миллионов пользователей во всем мире, которые содействуют переводу этого проекта на свой родной язык, чтобы поделиться опытом онлайн-скорости с помощью загрузчика DAP.
Как DAP увеличивает скорость загрузки
- Разбивая файлы на более мелкие части;
- скачивая файлы из нескольких источников одновременно;
- находя быстрые зеркала.
DAP предлагает дополнительные функции в виде « add-ons «. Включив их, вы сможете сэкономить время при загрузках, а также еще дополнительно увеличить скорость загрузки (от 200 до 400% быстрее, во многих случаях).
Одним из наиболее полезных дополнений, которое вы можете включить, является DAPsters Manager . Если вы загружаете файлы с RapidShare.com или аналогичных сайтов, эта функция вам пригодится. В основном это сводит к минимуму «раздражающие» страницы, которые обычно предшествуют скачиванию файлов.
Еще одно «великое» дополнение — Link Checker , которое определяет допустимые и недопустимые ссылки, прежде чем вы нажмете кнопку «download». Оно показывает небольшой значок рядом с действительными ссылками на страницы загрузки, так что вам не придется тратить время, пытаясь скачивать из всех различных источников подряд.
Другие дополнения включают в себя Медиа Просмотр, Просмотр почты, Интернет-Браузер и Видео Downloader https://softgallery.ru/download-accelerator-plus/» target=»_blank»]softgallery.ru[/mask_link]
DAP — Программа для редактирования звука в Linux
Если вы хотите редактировать звуковые файлы, загрузите программу DAP (как правило, программы редакции звука в дистрибутив системы не входят). Аббревиатура DAP расшифровывается как Digital Audio Processor. Программа изначально работает со звуковыми файлами формата AIFF, однако может также открывать и сохранять файлы форматов WAV и RAW. Помимо файлов моно и стерео, программа умеет работать и с квадрофайлами.
Сегодня скачать сэмплы может каждый музыкант. Сделать это можно на сервисе freshsound.org. Большой выбор сэмплов для fl studio, сэмплов dubstep и множество других к вашему вниманию.
Для загрузки AIFF-файла в программу выберите в меню File пункт Open, а для загрузки WAV-файла — пункт Import Wav. В открывшемся окне выберите нужный файл и щелкните на кнопке Ready. Программа покажет волновую форму загруженного файла.
Для того чтобы проиграть звуковой файл, откройте окно управлением проигрывания файла щелчком на кнопке Play в основном окне. Откроется дополнительное окно. Здесь имеются следующие элементы управления:
- Sample –проиграть весь файл;
- Range – проиграть выделенную часть файла;
- Display – проиграть ту часть файла, волновая форма которой отображена в окне;
- Stop – остановить проигрывание;
- Hardware Mode – выбрать подходящий режим для вашего звукового оборудования (стерео или квадро);
- Display Scroll Auto – автоматически прокручивать волновую форму при проигрывании;
- Output Levels – регуляторы громкости звука на выходе;
- Lock – установить одинаковую громкость на выходе для правого и левого каналов;
- Mute – отключить звук на выходе;
- Output Rate – частота дискретизации на выходе.
Помните, что все установки громкости в окне управления воспроизведением (Play) относятся только к прослушиванию звука и не изменяют сам звуковой файл.
Вас могут заинтересовать другие материалы:
Warning: call_user_func_array() expects parameter 1 to be a valid callback, function ‘actions_post_nav’ not found or invalid function name in /var/www/ch8648adac/www/linuxgid.ru/wp-includes/class-wp-hook.php on line 288
Источник: linuxgid.ru