Перейти к публикации
  • 0
Teen_Romance

Работа условного оператора if

Вопрос

Хотел сделать так, чтобы если ячейка сундука пустая, то проверка не выполнялась, но все равно ругается почему то программа :(

image.png.ddd7a8ff55efa9f90b2bfb4c12ab7490.png

Типа если y(nil) тогда не выполнять следующий иф.

image.png.852e6808def0e90712a684863151c16c.png

Как пофиксить?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Рекомендованные сообщения

  • 0

Ну как где? "pe4[stack.id]" - тут и сравнивает. Если таблица pe4 содержит элемент с ключом, эквивалентным значению поля id таблицы stack, то результатом будет значение элемента таблицы pe4 по требуемому ключу.

 

Да, для того, чтобы ветвь if выполнилась, все условные элементы должны отличаться от nil. И нет, первая часть условия далеко не всегда будет истинна: если требуемый слот не содержит предметов, то переменная stack будет иметь значение nil. 

 

Для работы программы нужно банально пробежаться по всем слотам сундука, проверить, есть ли что-либо в слоте - и если есть, то проверить, является ли id предмета в слоте валидным (т.е. содержится ли он в таблице pe4). По крайней мере, я именно так понял условие задачи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Скорее всего, cry.getStackInSlot(j) для пустого слота возвращает пустую таблицу. Избежать исключения можно, проверив наличие поля cry.getStackInSlot(j).id.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

@eu_tomat Возможно я не так понял, но я сделал вот так:

image.png.634409ff92088d7f125e5dc829817ed9.png

И теперь ошибка в том что не может дать индекс полю если пустой слот и не выполняет вообще ничего:

image.png.b157cfd78c0f934f7b6a46085b3b7b6e.png

ну и собственно если поменять y=cry.getStackInSlot(j).id то получаю ту же  ошибку

Изменено пользователем Teen_Romance

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

zX5OdLjFMis.jpg

Проблема именно в том что программа не может индекс дать пустому слоту в 7 строке :(

Изменено пользователем Teen_Romance

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
11 минут назад, Teen_Romance сказал:

Проблема именно в том что программа не может индекс дать пустому слоту в 7 строке :(

Что значит "не может дать индекс"? Как выглядит ошибка? Какая версия OpenComputers?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

OpenComputers-MC1.7.10-1.6.2.12-universal - так называется файл в папке mods.

image.png.83395d47ca5b4ab84ec1256cbccd8d27.png

вот так выглядит ошибка

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Что такое crystal ? Все перебрал в МЭ так и не нашел этой штуки.

И вообще покажи что за установка, чтобы можно было воссаздать и протестировать. А то так долго можно перебирать и предполагать "а если ..."

Изменено пользователем Asior

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

@Teen_Romance

local stack
for i = 1, 10 do
  stack = cry.getStackInSlot(i)
  if stack then
    -- Делай чо надобно
  end
end

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

@ECS Вот код :

image.png.ec4a3ba312c71eda1c7399ce17262911.png

Вот ошибка:

image.png.57c221ce9c08730eb9ac87dc740fc411.png

Насколько я понимаю, указывает ошибку на 10 строку, а значит if stack then все равно не работает 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

@Asior crystal - это имя компонента Кристального сундука.

Больше 200 кб скрин я почему то не могу загрузить,  поэтому вот скрин установки.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Ни у кого большое не осталось идей как пофиксить это? Проблема где то в логике, но я не могу понять где (

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Идеи есть, но я пока не добрался до компа с Майнкрафтом, чтобы проверить.

Можешь показать значения cry.getStackInSlot(i) для пустых и заполненных слотов?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
31 минуту назад, Teen_Romance сказал:

Ни у кого большое не осталось идей как пофиксить это? Проблема где то в логике, но я не могу понять где (

Мяу, ну написали же русским языком, что getStackInSlot(номер слота) возвращает таблицу с информацией о предмете, если таковой имеется в слоте - либо nil в том случае, если слот пустой, для чего и нужна проверка на "пустотность".

 

Шаг 1. Получил инфу о предмете в слоте

stack = getStackInSlot(i) 

Шаг 2. Убедился, что в слоте есть предмет

if stack then

Шаг 3. Обработал информацию о предмете в слоте так, как требуется. НЕ НУЖНО вызывать getStackInSlot() еще раз. Переменная stack уже хранит результат вызова getStackInSlot()

if stack.id == 8 then

Конкретно в твоем случае ошибка происходит по той причине, что getStackInSlot возвращает nil, а ты пытаешься получить поле от возвращаемых данных по ключу id - вот и получаешь ошибку attempt to index a nil value. Слот пустой, id не существует. Делай проверку разово - и работай с переменной stack.

 

Также я не совсем понимаю, почему ты используешь два цикла for i = 1, 10 / for j = 1, 10, когда число предметов в ME-сети явно может превышать 100. Наверняка там должен иметься метод getInventorySize, или getItemCount, или еще какой-то схожий - используй его.

 

И еще: для сравнения id предметов с таблицей pe4 также придется делать отдельную логику. Что-то наподобие:

local pe4 = {
  [1] = "камушек",
  [8] = "доски"
}

...

stack = cry.getStackInSlot(i)
if stack and pe4[stack.id] then
  print("рассматривается валидный предмет")
end

Кроме того, как заметил @Asior, мы понятия не имеем, что это за компонент такой под названием "crystal". Так что если выяснится, что информация о его stack'ах вообще не содержит никаких id, либо его id является строковым наподобие "minecraft:stone" - то тут уж ты сам виноват. ПоДуМоЙ

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Компонент crystal, это прозрачный сундук из мода ironchest, подключается модом OpenPeripheral.

Нумерация начинается с единицы, cry.getStackInSlot(i) возвращает таблицу с описанием содержимого слота или nil, если слот пустой.

 

Код из стартового поста выглядит работоспособным, и я пока не вижу проблему.

@Teen_Romance можешь выложить код не скриношотом, чтобы я его запустил у себя?

А ещё нужны версии ironchest и OpenPeripheral.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
3 часа назад, ECS сказал:

Конкретно в твоем случае ошибка происходит по той причине, что getStackInSlot возвращает nil, а ты пытаешься получить поле от возвращаемых данных по ключу id - вот и получаешь ошибку attempt to index a nil value. Слот пустой, id не существует. Делай проверку разово - и работай с переменной stack.

Проснулся и после прочтения всего что вы тут писали понял: ошибка из за того что первым фором (for i=1,10) я прохожу по таблице с рецептом (таблица pe4 ) в которой всего 2 ключа(или 2 таблицы внутри, не знаю как правильно сказать). А вторым фором(for j=1,10) я прохожу по ячейкам кристального сундука, для сравнения рецепта (pe4) и наличия ресурсов в сундуке. А из за того что первый for 10 раз идет по таблице в которой всего 2 элемента я  получал ошибку(Так глупо что аж ...:( ). 

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

Также я не совсем понимаю, почему ты используешь два цикла for i = 1, 10 / for j = 1, 10, когда число предметов в ME-сети явно может превышать 100. Наверняка там должен иметься метод getInventorySize, или getItemCount, или еще какой-то схожий - используй его.

Я просто давно не работал с OC и сейчас маленькими кусочками вспоминаю что и как работает. На скринах это просто куски программы ничего по сути пока что не делающей. 

2 цикла for я использую чтобы первый проходил по таблице с рецептом, а второй по ячейкам сундука(Ведь нужные ресурсы могут быть не только в первых 2,3,4,10 слотах). 10 я в цикле указал просто так, для теста, я понимаю что в сундуке около 100 ячеек. Не знаю насколько это рационально использовать 2 фора, но как я говорил выше, я просто пробую что и как работает)

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

И еще: для сравнения id предметов с таблицей pe4 также придется делать отдельную логику. Что-то наподобие:

Возможно с этим у меня в будущем возникнут проблемы, но я пока что просто проверяю что и как работает. Попробую пока что использовать для проверки ресурсов в сундуке и сравнения с рецептом, то что у меня на скринах. А вообще я хочу написать программу для автокарфата вещей на варпе. Типо  на компе выбираешь дробитель из IC2, тебе показывает какие и  сколько ресурсов нужно, ты кладешь их в сундук и для тебя делается дробитель. Хочется еще сделать граф оформление(чтобы по экрану можно было клацать) поэтому у меня в скором времени появятся вопросы с event и GUI :) А то на вики чет вообще ничего не понятно.

Спасибо всем кто помогал :) 

Изменено пользователем Teen_Romance

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
11 минут назад, Teen_Romance сказал:

Проснулся и после прочтения всего что вы тут писали понял: ошибка из за того что первым фором (for i=1,10) я прохожу по таблице с рецептом (таблица pe4 ) в которой всего 2 ключа(или 2 таблицы внутри, не знаю как правильно сказать). А вторым фором(for j=1,10) я прохожу по ячейкам кристального сундука, для сравнения рецепта (pe4) и наличия ресурсов в сундуке. А из за того что первый for 10 раз идет по таблице в которой всего 2 элемента я  получал ошибку

Кхе. Я ожидал увидеть кривую работу компонента, а ошибка возникла в своей же таблице. Ларчик просто открывался.

 

Кстати, выше @ECS предложил более удобный вариант поиска элемента по id в качестве ключа, что избавляет от цикла:

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

if stack and pe4[stack.id] then

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
8 минут назад, eu_tomat сказал:

Кстати, выше @ECS предложил более удобный вариант поиска элемента по id в качестве ключа, что избавляет от цикла:

Я не понимаю в чем фишка этого варианта. Грубо говоря stack это таблица с кучей инфы от проверки жидкость ли это до dmg. А что у меня получится если я напишу pe4[stack.id] - я не понимаю. Типо ключем таблицы будет допустим "minecraft:cobblestone" и что дальше? И что вообще делает if stack and pe4[stack.id] then. Если в таблице stack(то есть в ячейке сундука) что то есть, и в таблице с ключем stack.id(имеется в виду что ключем будет тоже "miecraft:cobblestone" как я понял) что то есть, тогда что то там. Вообщем как то сложновато (

Изменено пользователем Teen_Romance

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
1 час назад, Teen_Romance сказал:

Я не понимаю в чем фишка этого варианта.

Это просто более удобный и быстрый вариант проверки наличия id предмета из сундука в твоей таблице pe4. Можно, конечно, делать сие через цикл - но зачем? Ключом элемента таблицы может быть что угодно: хоть число, хоть строка, хоть функция, хоть таблица - это уж как тебе удобно. Просто если поле id у предмета - это "minecraft:cobblestone", то и таблица pe4 для корректного поиска должна выглядеть соответствующе:

pe4 = {
  ["minecraft:cobblestone"] = true,
  ["minecraft:wood"] = true,
}

А конструкция "if stack and pe4[stack.id]" работает именно так, как ты и предположил - сначала проверяет наличие предмета в слоте,  а затем уже сверяет id с твоей таблицей

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
6 минут назад, ECS сказал:

А конструкция "if stack and pe4[stack.id]" работает именно так, как ты и предположил - сначала проверяет наличие предмета в слоте,  а затем уже сверяет id с твоей таблицей

А где она сравнивает id с таблицей? "if stack and pe4[stack.id]" Разве для того чтобы ветвь if выполнилась выражения должны быть равны между собой?  Разве не просто проверяется их пустота? Тип если stack не пустой и pe4[stack.id] не пуста тогда что то делается. Правая часть условия всегда будет истинна, но где они сравниваются? И вы имеет ввиду вообще без цикла или только с 1 фором? По ячейкам сундука ведь мне все равно нужно проходить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
3 минуты назад, ECS сказал:

Ну как где? "pe4[stack.id]" - тут и сравнивает. Если таблица pe4 содержит элемент с ключом, эквивалентным значению поля id таблицы stack, то результатом будет значение элемента таблицы pe4 по требуемому ключу.

Минуты 2 сидел вчитывался и не мог понять фишку, а потом каааак понял 🤣 На самом деле гениально, просто звучит сложно. Если элемента по такому ключу в таблице не будет то выражение просто будет равно nil )

Сложно как то еще применить но я подумаю)

Спасибо большое еще раз :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

@Teen_Romance, замищательно! Держи тяночку. Она тоже искала идшники в таблицах, но что-то пошло не так...

 

0puzZUDCa7o.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
15.03.2019 в 16:02, Teen_Romance сказал:

Минуты 2 сидел вчитывался и не мог понять фишку, а потом каааак понял 🤣 На самом деле гениально, просто звучит сложно. Если элемента по такому ключу в таблице не будет то выражение просто будет равно nil )

Сложно как то еще применить но я подумаю)

Спасибо большое еще раз :)

Вот тебе еще один способ сравнения:

local prefix = "Я знаю, это "
local function unknown()
  print("Об этом я не ничего знаю")
end

local indexer = {
  __index = function(self, key)
    local value = rawget(self, key)
    if value then
      return function() print(prefix .. value) end
    else
      return unknown
    end
  end
}

local knowns = {
  ["minecraft:cobblestone"] = "опять чертова кобла",
  ["minecraft:planks"] = "доски",
  ["minecraft:tnt"] = "кубик веселья",
  ["minecraft:log"] = "бревно, как моя бывшая"
}

setmetatable(knowns, indexer)

local me_controller = require("component").me_controller

for _, item_stack in pairs( me_controller.getItemsInNetwork() ) do
  print(item_stack.label, " = ", item_stack.size)
  knowns[item_stack.name]()
end

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Это точно рабочий код? Есть у меня сомнение, хотелось бы развеять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
7 минут назад, Zer0Galaxy сказал:

Это точно рабочий код? Есть у меня сомнение, хотелось бы развеять.

Я не тестировал. Каковы сомнения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
Только что, man_cubus сказал:

Я не тестировал. Каковы сомнения?

Сомнение в том, что __index вызывается только при отсутствии элемента в таблице.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
6 минут назад, eu_tomat сказал:

Сомнение в том, что __index вызывается только при отсутствии элемента в таблице.

Неправда

t = {1,2,3,4}
mt = {__index=function(self, key) v=rawget(self,key) if v then return v else return "shit!" end end }
setmetatable(t,mt)

for i=1,6 do print(t[i]) end

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
3 минуты назад, eu_tomat сказал:

@man_cubus И что доказывает этот код?

Действительно, тут нужна прокси таблица. Вот исправленная версия

 

local prefix = "Я знаю, это "
local function unknown()
  print("Об этом я не ничего знаю")
end

local descriptions = {
  ["minecraft:cobblestone"] = "опять чертова кобла",
  ["minecraft:planks"] = "доски",
  ["minecraft:tnt"] = "кубик веселья",
  ["minecraft:log"] = "бревно, как моя бывшая"
}

local indexer = {
  __index = function(self, key)
    local value = descriptions[key]
    if value then
      return function() print(prefix .. value) end
    else
      return unknown
    end
  end
}

local knowns = {}

setmetatable(knowns, indexer)

local me_controller = require("component").me_controller

for _, item_stack in pairs( me_controller.getItemsInNetwork() ) do
  print(item_stack.label, " = ", item_stack.size)
  knowns[item_stack.name]()
end

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Похоже, ты не уловил сути метатаблиц. Нет, теперь то код рабочий. Но какой смысл в метатаблице если сама таблица knowns не содержит элементов? Просто вызывай функцию __index и всё.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Вот я о чем:

local knowns = {"A","B","C"}
local indexer = {
  __index = function(self, key)
      return "unknown"
    end
}

setmetatable(knowns, indexer)

for i=1,5 do
	print(knowns[i])
end

результат:

A
B
C
unknown
unknown

т..е. __index стреляет только для тех элементов, которые отсутствуют в таблице knowns.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Гость
Ответить на вопрос...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.


×