All streams
Search
Write a publication
Pull to refresh
40
0
Павлов Николай Александрович @ZyXI

Инженер

Send message

next() — выглядит как более короткий хак, чем с pairs. И не решает проблему если нужен именно размер, а не проверка на пустоту. Размер «массива» тут не в тему.


PS: Размер таблицы‐массива узнаётся за O(log(table_size)) (O(table_size), если размер таблицы больше MAX_INT/2 или таблица специальным образом построена) в lua. Не знаю, что в luajit (но тесты показывают, что чтобы там ни было, оно не даёт O(1)), но в lua-5.3.4 используется бинарный поиск; в лучшем случае бинарный поиск по массиву, в худшем — по хэшу. Они как‐то ухитряются делать это быстро (скорее всего, мои тесты просто все прошли как бинарный поиск по массиву), но идея мне всё равно не нравится.

На JS я практически ничего не писал, поэтому сравнить не могу. Но второе негативное ощущение от lua — это стандартная библиотека, выглядящая как куча недоделок:


  • Из всех возможных манипуляций с переменными окружения вам доступно только получение значения переменной. Получить полный список, а также добавить либо изменить значение нельзя.
  • Нельзя менять рабочий каталог.
  • Есть удаление каталогов, но рекурсивное удаление вам придётся писать самим.
  • Есть два способа запустить процесс, но ни одного — запустить со списком аргументов. Чего‐то вроде shellescape() тоже нет.
  • Нельзя запустить процесс в фоне и общаться с ним. Можно только либо читать его вывод (документация, кстати, не говорит о том, будет ли это stdout, stderr или оба сразу, но проверка показывает, что только stdout), либо писать ему в stdin.
  • В регулярных выражениях есть такие вещи как %{number} или %b(), но нет банального |. И ещё регулярные выражения не компилируются, так что вы можете только надеяться на оптимизатор, либо на то, что компиляция не занимает долгое время (что, скорее всего, говорит о низкой скорости работы результата).
  • Нельзя узнать число элементов в таблице. В т.ч., проверить не пуста ли она, не используя pairs().
  • Upstream нарушает обратную совместимость в минорных версиях. В частности, из‐за этого «нет» побитовых операций в стандартной поставке — обновляться с 5.1 просто нельзя, т.к. многие нужные пакеты забили на обновление. Команда luajit работает в этом отношении намного лучше.

Я не ожидаю Python’овского «batteries included», но мало что из того, что всё‐таки есть, выполняет свои функции полностью.


Ещё, я совершенно не понимаю, почему нельзя писать {}[key] и "%d":format(num) без дополнительной пары скобок. Полагаю, это потому, что func 'abc'.foo работает как (func('abc')).foo (с таблицей аналогично), но не понятно, зачем было делать выбор в пользу менее читаемого синтаксиса.

Ещё можно отметить то, что в таблицах нельзя хранить nil, зато отсутствующие в таблице ключи и неопределённые переменные имеют это значение. Иногда удобно, но слишком часто служит источником ошибок. Кроме того, языком полностью игнорируется расхождение в числе аргументов при объявлении и вызове функции — недостающие аргументы просто забиваются nil’ами (если только функция не с ... — тут вы всегда можете понять, использовали ли nil или просто не написали аргумент), «лишние» аргументы молча игнорируются.

Ожидал увидеть описание приложения, реализующего VPN‐over‐что‐то (пример с DNS и для linux; для Android есть именно VPN‐over‐DNS, но я не видел про него статьи). Но тут всего лишь короткая заметка про сайт с iframe.

Какой компилятор lua в LLVM? Я нашёл только устаревший (последнее изменение в январе 2012) llvm-lua и вот такую ветку комментариев, предположительно, от автора, о том, что llvm-lua потребляет слишком много ресурсов и не годится для этой задачи.


А в javascript, нативный код, Java (точнее, GraalVM) можно всё, что LLVM поддерживает. Может и в .net можно, в поиске слишком много результатов про использование LLVM как компилятора для .net.

А что не так с


// Autogenerated, do not edit. All changes will be undone.

?

Я видел быструю операционистку без десятипальцевого набора. Половина времени — переключение на мышку, слепая печать в школе тут поможет только из расчёта «может дизайнеры приложений будут больше времени уделять возможности не отрывать руку от клавиатуры, а менеджеры — обучению использованию этой возможности». Но, скорее всего, этого не случится.

Я вообще не знаю, зачем в школе учить создание GUI. Но «особые случаи» проще и всё ещё полезны.

Почему не делают? Простые GUI вроде примеров из Взаимодействие bash-скриптов с пользователем пишут безо всякого ООП. Ещё есть LabVIEW, используется у нас на работе — «лицевые панели» виртуальных приборов вполне себе GUI. «Внутрях» у kdialog и LabVIEW, может, и какой‐нибудь C++ (а у второго, может, и нет, я не знаю), программист для создания GUI на основе этих инструментов ООП использовать почти наверняка не будет.


Из чего‐то более сложного я могу вспомнить только про Web‐приложения и то, что не все javascript framework’и, про которые можно прочитать на хабре, используют ООП. Но в любом случае, «давно никто не делает» и «в сложных графических приложениях (почти?) всегда используется ООП» — это совершенно разные вещи.

У нас в школе были и ассемблер, и лого с черепашкой, и какие‐то CISCO’вские курсы по сетям. Вопрос в том, какие цели у курса информатики: понимание, как работает компьютер и понимание, как эффективно за ним работать — это уже разные вещи и «слепая печать» относится ко второй, многопоточное программирование (и ассемблер, но не GUI и не ООП) к первой. А не слишком пригодный для написания скриптов Pascal нужен вообще для третьего: чтобы школьники научились структурному программированию (или хотя бы просто научились программировать).


Конкретно для «осознанной профориентации» в минимальное время, вообще‐то, лучше взять … POSIX shell. И затронуть сразу профессии программиста и администратора, попутно показав как можно облегчить себе жизнь скриптами и дав один из широко и реально используемых языков. А лишнее время направить на информационную безопасность, с практикой, углублённым объяснением механизмов работы уязвимостей (ещё в таком контексте объяснение «как работает компьютер» пойдёт куда лучше) и пропагандой открытого кода импортозамещения.

Связи лучше подсвечивать, создавая жирный красный фон, а не перекрашивая их: в LabVIEW много недостатков, но разноцветные линии разной фактуры, соответствующие разным типам к ним не относятся. Но такая подсветка типов плохо совместима с перекрашиванием на diff’е. Ещё одна проблема для diff’ов (кстати, у меня также не решённая, нужно переделать предложение по нумерации узлов; только то, что я пока могу придумать сделает их названия сильно длиннее): если я удалил узел и вставил на место точно такой же, то они подсвечиваются также, как если бы я вставил другой узел (т.е. один удалён, один добавлен).

Оператор от подобной функции будет отличаться тем, что если default_value — на самом деле какое‐то вычисляемое выражение, то оно вычисляться не будет. Судя по картинке выше, называть новые функции «оператором Элвиса» неверно (иначе зачем существует Get версия?), но когда я прочитал про это в статье, то очень удивился: оператор, выглядящий как функция — разработчики Java совсем с ума сошли?

Главное, что в вашем примере все данные о нодах хранятся в одном месте, и ещё это JSON. Получить нормальные diff’ы в текстовом виде вам так не светит¹: diff любит помещать скобочки не там, где нужно (с т.з. читаемости), у JSON принципиальная проблема с завершающей запятой (которая также плохо отражается на diff’ах), а часто повторяющиеся метаданные вроде "group": null делают «проблему скобочек» ещё острее. Ну и при чтении diff’а положение узлов в графике не важно совершенно (пока не увидите, не поймёте, нормально ли получилось), а такие изменения будут перемешиваться с логикой.


А про «графический diff»: во‐первых, сложно сделать удобно. Во‐вторых, ну сделаете вы графический diff, а смотреть его как? Схемы хранятся в VCS, VCS обычно является частью чего‐то более крупного вроде github, а веб‐интерфейс «чего‐то крупного» показывать ваши diff’ы не умеет, и учиться не будет, пока вы не станете достаточно популярны (впрочем, в некоторых случаях вы можете научить его сами различными способами, в т.ч. дополнениями для браузера). Если придумать правильное представление, то можно хотя бы получить возможность делать review на уровне «а следует ли мне вообще идти смотреть графический diff», а в идеальном случае должно даже позволить себя читать.


¹ Плюс ещё LabVIEW позволяет размещать провода как вы хотите, а не «у нас соединение с нодой X, а провод проведём как‐нибудь сами»; и у того, и у другого варианта есть плюсы и минусы, но diff’ы в случае, если вы засунете описание пути провода к описанию соединений, станут ещё менее читаемыми.

Разумеется. Я просто написал, как бы я подошёл к представлению виртуальных инструментов LabVIEW для случая «нужно получить хотя бы относительно читаемый diff», а, возможно, иногда даже получать нормально работающее слияние виртуальных инструментов как текстовых файлов. Соответственно, и метаданные, и код, и представление должны быть все представлены в этом файле.


Текст, что выше должен описывать простейший виртуальный инструмент, который вызывает виртуальный инструмент My Wait.vi с данными из терминала timeout, в случае, если на входе нет ошибки, и пересылает ошибку на выход, если она есть. Правда, я уже заметил у себя ошибки, но на идею они не влияют.

Я как‐то думал, как выглядело бы представление LabVIEW’шных виртуальных инструментов в формате, который производил бы относительно читаемые diff’ы. Основная суть идеи в том, что метаданные отдельно, логика отдельно, представление отдельно. Если правильно выбрать способ сортировки данных одного уровня иерархии и разбивки на строки, то можно получить относительно читаемые diff’ы. Правда, в моём примере ниже нужно больше внимания уделить алгоритму генерации имени проводов.


Если что, получилось что‐то вроде (мысленно удалите комментарии)


%YAML 1.2
---
description: Wait for delay milliseconds.
# …
# Other metadata from VI properties
# …
icon:
    palette:
        a: {A: 0x00, R: 0x00, G: 0xff, B: 0x00}
        b: {A: 0x00, R: 0x00, G: 0xff, B: 0x00}
    # “Image” key uses single-character ARGB colors from palette.
    # UTF-8 in case ASCII is not enough.
    image: |
        bbbbbbbbbb
        baaaaaaaab
        bbbbbbbbbb
        baaaaaaaab
        baaaaaaaab
        baaaaaaaab
        bbbbbbbbbb
terminals:
    pattern:
        left: 3
        top: 0
        bottom: 0
        right: 3
    list:
        - name: delay
          caption: "delay (default 5000 ms)"
          location: left 0
          direction: input
          type: I32
        - name: error in
          caption: "error in (no error)"
          location: left 2
          direction: output
          type: error cluster
        - name: error out
          caption: error out
          location: right 2
          direction: output
          type: error cluster
code:
# Code: contains all used nodes and their relations, but not their positions
# or positions of the wires.
#
# The code is created as following: first all node names are determined.
# Then AST is sorted so that if node B has inputs wired to outputs of node A
# then node A appears first. Should that not allow determining the order
# then nodes are sorted alphabetically.
#
# After sorting is complete all nodes are appended indexes to make them
# unique. Indexes are tracked in runtime and preserved so the below index
# order only keeps being perfect on the first save.
#
# Note: if node was replaced via “Replace” context menu it still keeps its
# index: this is one of the main points in having global incrementing indexes.
#
# Inputs/outputs are named after their nodes with terminal names appended.
# Should terminal name be not unique its position is appended.
#
# Only inputs/outputs which have wires receive their names: names in
# node dictionaries define connections.
- control/delay 0: {output: control/delay 0/output}
- control/error in 1: {output: control/error in 1/output}
- case structure 2:
    selector: control/error in 1/output
    # Terminal properties which do affect logic are defined here
    use default if unwired:
    - indicator/error out 5/input
    cases:
        Error:
        # In some cases there is nothing, but wire; and it is significant
        # for the logic.
        - wire: !!set {control/error in 1/output, indicator/error out 5/input}
        No Error:
        # User VI: same as default ms waiter, just to show how it would look.
        #
        # Dictionary near the node maps terminals to connections.
        - My Wait.vi 4: {wait: control/delay 0/output}
- indicator/error out 5: {input: indicator/error out 5/input}
# Define wire positions in a form [anchor (output terminal), relative
# x/y offset, anchor (input terminal)]. Wires without sources or with structure
# terminals as sources are listed from sink. Wires without sources or sinks just
# use [anchor, node name] with nearest anchor. No absolute positions used ever.
#
# Note: determining exact anchors still needs code above, pairs in wire
# position only reference nodes.
#
# Since wire may have more then one sink this is a list of lists of lists,
# innermost list is a 2-tuple (type, data).
#
# Structure terminal positions are also defined here.
wires:
    control/delay 0/output:
    - [[source, control/delay 0], [structure terminal, [case structure 2, +1, 0]], [case, No Error], [sink, MyWait.vi]]
    control/error in 1/output:
    - [[source, control/error in 1], [structure terminal, [case structure 2, +1, 0]], [case, Error], [structure terminal, [case structure 2, +5, 0]]]
    indicator/error out 5/input:
    - [[sink, indicator/error out 5], [structure terminal, [case structure 2, -1, 0]]]
# Node positions and properties that do not affect logic.
nodes:
    control/delay 0:
        type: control
        terminal: delay
        # Position is absolute
        position: [0, 1]
        label:
            # label position relative to position
            position: [-1, -1]
            visible: true
        view: icon
    control/error in 1:
        type: control
        terminal: error in
        position: [0, 0]
        label:
            position: [-1, -1]
            visible: true
        view: icon
    case structure 2:
        type: case structure
        position: [1, 2]
        size: [5, 2]
        label:
            text: Case Structure
            visible: false
            position: [0, 0]
        # Case visible by default
        selected case: No Error
    MyWait.vi 4:
        type: VI
        # Logical location (which structure, which case) is defined by logic.
        position: [2, 1]
        label:
            position: [-1, -1]
            visible: false
        view: icon
    indicator/error out 5:
        type: indicator
        position: [6, 0]
        label:
            position: [-1, -1]
            visible: true
        view: icon

Про кнопку не знал, но проблемы она не снимает: клавиатурное сочетание на все действия по выравниванию одно. Буду на работе, посмотрю, нельзя ли назначить разные на разные действия, а не одно на повторение последнего действия.


Блоки не всегда подходят: в хосте можно что‐то сообразить на куче различных видов ссылок или с глобальными переменными, но на FPGA первого нет, а второе жрёт ресурсы, из‐за чего такое объединение получается менее оптимальным, чем хотелось бы (в смысле, либо жрёт ресурсы, либо требует выноса в основную VI того, что я на хосте выносить не стал бы). (Впрочем здесь есть возможность задействовать VHDL, только пока руки не дошли.)

LabVIEW позволяет размещать комментарии в произвольном месте, что даёт возможность подписывать длинные провода и неочевидные моменты. Плюс названия циклов и фреймов, если они не очевидны или если мне захотелось их назвать. Ну и необходимые вещи вроде названий VI’ек и их иконки.


Вообще‐то у LabVIEW есть какая‐то система документирования, но т.к. я, во‐первых, не знаю, как посмотреть документацию из свойств VI методом, отличным от «открыть VI и пойти смотреть свойства», и, во‐вторых, такая документация относится только к VI целиком и частично закрывается нормальным названием файла и иконкой, то мною эта функциональность как раз‐таки не используется.

А я на нём «пишу» (на версии 2015). Нет практически никаких средств улучшения представления кода, даже аналогов команд из Altium Designer «выровнять по левому/правому/верхнему/нижнему» краю, из‐за чего бо́льшая часть времени тратится на то, чтобы «код» был поддерживаемым. Нет масштабирования! Проблема с «цикломатической сложностью на пиксель» элегантно «решается» блоками вроде «case structure», которые в принципе не позволяют увидеть весь код сразу.

Нормально у них с мозгом, потому что они нормально выполняют свою работу. А у меня ответ был на то, что в бюджетных учреждениях зовут «программистов» на каждый чих: в тех учреждениях, с которыми я контактировал, не зовут.

Не раз видел как в бюджетном учреждении (МФЦ) сотрудники вполне себе доставали из принтера картридж (с целью потрясти или обнаружить замятую бумагу) или замятую бумагу (с открытием различных дверок и возможным доставанием картриджа). Вероятно, у вас либо возможность что‐то печатать не так уж критична, либо проблемы с принтером возникают редко. Впрочем, есть ещё вариант с другой проблемой: пользователь просто не знает, у кого картридж на балансе, и, соответственно, может ли он его себе вставлять вообще.


Кстати, работал в финансовой/риэлторской конторе курьером, 3 (празднования, точнее, много празднований: корпоративы были, но не так уж много и денег не собирали, если не идёшь), 6 (границы) и 8 (начальственный ступор) не видел. 12 (нерешительные кадры), 13 (язык документации), 11 (внезапный декрет) и 10 (расходная часть) также не видел, но тут скорее «не замечал» либо «не мог заметить».

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity