Перейти к содержимому

Krutoy

Гуру
  • Публикации

    482
  • Зарегистрирован

  • Посещение

  • Победитель дней

    72

Сообщения, опубликованные пользователем Krutoy


  1. 20 часов назад, eu_tomat сказал:

    А что там в ролике за бутылочка, ускоряющая сборку робота?

    И как ты сделал рецепт крафта своей EEPROM?

    Бутылочка - Time In The Bottle из мода Random Things

    Рецепт я сделал с помощью мода CraftTweaker. Я ведь разрабатываю свой модпак и могу делать какие угодно рецепты.

    • Спасибо 1

  2. 1 минуту назад, eu_tomat сказал:

    Но в конечном-то итоге ты хочешь сократить количество символов не в коде Lua, а в коде на твоём специфическом языке. И если правила этого языка ты определяешь сам, то можно создавать в принципе любые правила. Например, можно любое выражение присваивания интерпретировать по правилам языка Си. В каких-то случаях присваивание продолжится, в каких-то случаях оно окажется однократным, а иногда будет и вовсе отсутствовать, как это бывает с результатами вызова функций.

    Ну да, в этом и суть. Я придумываю правила сам.

    Вот только я не пишу свой парсер. Я придерживаюсь синтаксиса Луа, а поэтому, не могу сделать из присваивания выражение.


  3. 13 часа назад, Taruu сказал:

      

    Идея крутая, но чую что тут не хватает аля SPA простого который тупо рисовал блок-схемы или человеко читаемый код. А при желании еще и разжевывал что каждая команда делает с примерами и видосами. Но там кол-во работы настолько большое что повеситься можно >_<

    Мне кажется, делать "читаемый код" тут бессмысленно. Это как когда ты был в школе - тебе объяснили что такое знак +. Там не было никаких SPA схем или "человеко читаемый код". Может, показали пару-тройку яблок что бы объяснить что такое сложение.

     

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

     

    Да и я если честно, сам не совсем понимаю, как делать "человеко-читаемый код" в функциональном программировании.

    Например, есть оператор "apply" или по-русски "применение". В моем коде он выглядит как f/n, где f - функция, n - число или boolean. Результат будет выглядеть вот так:

    -- f/n
    function(...) return f(n, ...) end

    А теперь еще раз используем "применение":

    -- f/a/b
    function(...) return (function(...) return f(a, ...) end)(b, ...) end

    У меня если честно мозг устает такой "читаемый код" делать. 😅

     


  4. В 03.03.2023 в 11:31, eu_tomat сказал:

     Какова конечная цель этого трюка?

    Цель этого трюка - сократить количество символов в коде.

     

    Пример из реального кода:

     

    У нас есть точка из Навигатора дрона 

    P=navigation.findWaypoints(300)

    Дальше по коду, мы полетим к этому вейпоинту, подождем, а затем выполним его название

    drone.move(table.unpack(P.position))
    while drone.getOffset() > 1 do sleep(1) end
    run(P.label)

    В моем сокращении это всё выглядит так: 

    P=i/Nf300Dm^Pp,s/1~'Dg!>1',_(Pl)

    Допустим, я сделаю ту функцию 

    function _P(v) P = v; return P end

    Тогда сокращение будет выглядить так:

     

    _P(i/Nf300),Dm^Pp,s/1~'Dg!>1',_(Pl)

    И это только увеличило количество символов на +1 😃


  5. Если кто то читает эту тему, подскажите - как сделать присваивание внутри выражения?

     

    Например, есть вот такой код:

    _1_
    
    function f()
      return _2_
    end

    Я могу менять только _1_ и _2_. Я хочу что бы в _2_ было присваивание и тут же использование этой переменной.

     

    Например

    a=robot.move -- присваивание
    not a(3) and robot.turn(true) -- выражение

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

    function _a(v)
      a = v
    end
    
    function f()
      return _a(robot.move), a(3)
    end

     


  6. В общем, похоже вырисовывается в какой-то мере стабильно работающий код.

     

    Пока вся документация на английском:

    https://github.com/Krutoy242/lostuser

     

    В общем, я сохранил правила укорачивания и добавил больше функций между таблицами и функциями.

     

    Приведу пример дрона, который носит предметы между точками.

     

    36HdGzO.gif

     

    Компоненты: Инвентарь, Контроллер инвентаря

    Имя дрона:

    P=i/Nf300Dm^Pp,s/1~'Dg!>1',_(Pl)

    Описание каждой части имени:

     

    • Nf300: Выполняет navigation.findWaypoints(300). Это никакое заранее указанное сокращение. Большая буква - это сокращение, которое получают все компоненты. navigation -> N, inventory_controller -> I и так далее.
    • i/Nf300: Здесь используется единственная предустановленная переменная i. i = порядковый индекс текущего цикла программы, начиная с нуля. i / table - специальная функция "Получить индекс по модулю" или t[i % #t + 1]. Все эти функции, которые есть математические операторы над таблицами, есть в документации. По смыслу мы просто пробегаем каждый цикл по следующему вейпоинту.
    • P=i/Nf300: Просто записываем в глобальную переменную P наш вейпоинт. Локальные переменные не могут сокращаться, поэтому мы используем глобальную. А еще, если буква будет большая, мы сможем сократить точку далее.
    • : просто один символ который будет заменен на return . Приму советы как избежать таких замен, что бы сохранить чистый Lua код 🙂
    • Dm^Pp: вызывает drone.move(table.unpack(P.position)). Тут должно быть просто. Dm => D.m => drone.m => drone.move. В документации по ссылке выше перечислены все операторы, и там написано что если функцию (drone.move) возвести в степень таблицы (p.position) то мы получим вызов функции с раскрытием таблицы в параметры.
    • s/1~'Dg!>1' => while drone.getOffset() > 1 do sleep(1) end. Здесь символ ! заменяется на ()
    • _(Pl): Загрузить P.label как Lua код. Эта функция будет загружена и выполнена. Точки называются _'Dsk0'~4
        и _'Dsel(k)Dd(0)'~4 соответственно. Первая сосет 4 раза, вторая выбирает каждый из 4х слотов и поочереди их выбрасывает.
    • Нравится 4

  7. Продолжаю программировать.

    Понял что моя "труба" на самом деле называется "map". И теперь переписал код, что бы оператор map был через "*".

    Еще, "/" это `filter(v)`, а "%" это оператор "reduce(a,b)"

     

    T = q({{index=1},{name='n2'},{index=3}})
    print(T*'v.i'/'v'%'a+b') -- 4

    Осталось понять, что должно происходить, если мы делаем фильтр в таблицу или фильтр в число.


  8. 26 минут назад, ProgramCrafter сказал:

    Вроде machine.lua в OpenComputers запрещал так делать.

    Что ли, ещё один баг в OC нашёлся?

    А machine.lua есть на EEPROM ?

     

    Если да, то это досада =((

     

    UPD:

    Нашел... Печалька

    https://github.com/MightyPirates/OpenComputers/blob/master-MC1.12/src/main/resources/assets/opencomputers/lua/machine.lua#L730


  9. Я только что понял, что я могу изменять метатаблицы строк!

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

     

    Например, я могу добавить __bnot к строке, что будет ее загружать и превращать в функцию.

    getmetatable('').__bnot=function(s)return load('return '..s) end
    
    print((~'5*5')()) -- 25

     


  10. Ок, вот мои наработки по теме:

    https://gist.githubusercontent.com/Krutoy242/1f18eaf6b262fb7ffb83c4666a93cbcc

     

    Документацию напишу позже.

     

    Пока, как я и говорил, робот (или дрон!) умеет выполнять свое имя как Луа-код. Но к тому же, он может всё сокращать до 1-2 символов.

     

    Например, вот такая строка сторгует всё что есть у жителя:

    ~:Tg(){?!v{tr}}

     

    А вот мега программа в 54 символ для дрона, который носит предметы из одного вейпоинта к другому:

    Dm(tb.u(Nf(300)[a++%2+1].p))s(3)~#{Dsel(i)Dd(0)Dsu(0)}

    В этом примере есть такие сокращения:

    a++ это продвинутая версия a=a+1, только она работает даже если а==nil

    s(3) расшифруется как sleep(3)

    ~#{BODY} получится for i=1, (R or D).inventorySize() do BODY end

     

    Еще, я добавил крутые фичи связанные с "трубами" - как в лямбда программировании, когда мы можем скомпоновать функцию, которая будет передавать результат своей работы в другую функцию. Но пока не придумал как ими пользоваться.

     

    Главная фишка это утилизировать битовые операции. Я сделал такое: a|b превращается в function(c) return b(a(c)) end. Но оказалось, что это почти бессмысленно, если мы не можем получить ключ\значение из цикла.

     

    В итоге, я уже могу написать вот такую функцию:

    _4|(Dsel|Dd&0)

    Получится вот так (примерно):

    for k,v in pairs{1,2,3,4} do
      (function() return D.drop(0) end)(D.select(v,k))
    end

    Но как то криво всё равно. Не элегантно. Но уже можно пользоваться.

    • Нравится 3
    • В шоке 1

  11. 10 минут назад, eu_tomat сказал:

    У меня есть идея, но она ломает изначальный замысел. С точки зрения пользователя я бы предпочёл использовать стандартный синтаксис Lua, и чтобы все необходимые сокращения кода за меня выполняла программа. Получилось бы подобие упаковщика кода в последовательность ASCII-символов, которые можно было бы ввести через наковальню.

    Да, идея хорошая. Я думал такое сделать. Но по сути, это просто LZ77 алгоритм с распаковщиком внутри EEPROM.

     

    Вопрос такой - как узнать все доступные в наковальне символы? Не все символы можно вставлять в название, например

    §


  12. Может у кого то есть еще идеи как можно укоротить всякие конструкции с заголовком / телом ?

     

    В таких вещах как функции и циклы есть заголовок - например, таблица для pairs(t) и тело - собственно то что будет внутри блока.

    Самое короткое что я придумал - 3 символа.

    1. Ключевой символ начала паттерна

    2. Разделитель между заголовком и телом

    3. Окончание паттерна

     

    например вот тут ~:t{pt(k,v)} это ~:1 {2 }3

     

    Хотелось бы 2 символа или даже один.

    Например, как в лямбда - счислениях a.b означает b(a())

     

    Проблема в том, что в EEPROM запихать парсер Lua оч сложно, поэтому самый сильный инструмент у меня в доступе это "рекурсивный" паттерн %b12


  13. 15 минут назад, ProgramCrafter сказал:

    Лучше ~kv:t{pt(k,v)} (или как-то так), потому что циклы могут ведь вкладываться друг в друга.

    Да, но так еще больше символов.

    Вообще, я уже решил эту проблему. Все циклы работают через k,v, но при выполнении они переписываются на k0,v0 k1,v1 и так далее.

    ~:t{~:v{pt(k,v)}}

    получится

    for k1,v1 in pairs(t) do
      for k0,v0 in pairs(v1) do
        print(k0,v0)
      end
    end

     


  14. Размышления по поводу программы привели меня к еще более крутой идее:

    А что если я не буду придумывать никакого синтаксиса, а просто сделаю функцию сокращения путей и ключевых слов?

     

    Изменяя метатаблицы переменной _ENV я могу наворотить любые сокращения.

     

    Например, если назвать робота

    robot.use(3)

    - он будет юзать вперед.

    Но это можно укоротить до 5 символов. Заменим robot на R, сделаем поиск по полям, уберем ненужную точку, и вуаля, останется только 

    Ru(3)

    Еще бы сократить вызовы функции с параметрами как то, и вообще шикарно.

     

    Еще можно упростить всякие циклы и пэирсы, например заменить for in pairs() на

    ~:t{pt(k,v)}

    Превратится в

    for k,v in pairs(t) do
      print(k,v)
    end

    Но тут уже начинаешь путаться.

     

    🤔

    • Нравится 1

  15. 12 часа назад, rootmaster сказал:

    главный вопрос, а зачем? я в своих роботов либо ставлю монитор, либо подключаю к сети дома, регистрирую на нем удаленную файловую системму(чаще всего и то и другое)(мои софтом(netoworks, distfs2)) и открываю доступ в его lua по сети, и вооля все роботом можно управлять удаленно на диск записал /start.lua(запускаеться моим модом для openOS) и как тока включил он пойдет копать

    Моя версия проще. Лешего, не нужно учить луа. Скрафтил и вперёд.

    • Нравится 1
    • Одобряю 1

  16. 3 часа назад, ECS сказал:

    Респект за соулс от мира опенкомпов! 

    Спасибо!

    Тут как говорится - хотел как лучше - получилось как всегда.

     

    Цитата

    Пожалей наши мыши!

    Как? Я бы рад, но как?

    Может сделать какую то внутреннюю подпрограмму, которая будет расшифровывать все алиасы на месте? Типа, выводить куданибудь в output дерево расшифровки?

     

    Цитата

    ?{<a>==nil} эквивалентно if a == nil.

    Все твои шаги расшифровки почти полностью правильно поняли мою задумку. Мне приятно видеть что хоть кто то копнул так глубоко.

    Именно в этом шаге ?{<a>==nil} эквивалентно if VARS['a'] == nil, потому что иначе не нужны были бы <>.

     

    Цитата

    a - это программа, которая... что? Которая названа a

    Может, проблема в том, что в языке перемешан синтаксис языка \ алиасы и переменные? Может в таком случае, нужно что бы, например

    • Весь синтаксис только на не-буквеных символах @#$
    • Все переменные как маленькие буквы abc
    • Все алиасы как большие ABC
    Цитата

    классический эскейпинг через \" был бы правильнее

    В принципе, мне не сложно добавить эскейпинг. Я это сделаю.

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

     

    А может подключить юникод и сделать что то такое. Правда, при больших программах это все равно растянется на страницы

    gW79kp4.png

    • Нравится 1

  17. Нашел баг. 

     

    test(
      "true/false arguments",
      "a:true b:false c:c",
      function()
        f = L(
          function(a, b, c)
            return 'a:' .. tostring(a) .. ' b:' .. tostring(b) .. ' c:' .. tostring(c)
          end,
          'a', 'b', 'c'
        )
    
        return f(true)(false)()
      end
    )
    
    -- [Failed] true/false arguments
    -- Expected: a:true b:false c:c
    -- Got: a:true b:b c:c

     

    Тот самый случай, когда ты подумал "a and b or c" это настоящий условный оператор, а он подвел.

    Но я знаю как исправить, нужно просто заменить на "==nil"

    • Нравится 1
    • Одобряю 1
×
×
  • Создать...