Используйте Ruby для создания функции добавления DrRacket

Я пытаюсь использовать Ruby для эмуляции функции append из DrRacket. Однако, когда я пробую это, я получаю ((1 2 3) . 99) вместо (1 2 3 . 99). Можно ли правильно эмулировать append с помощью уже существующего списка или мне нужно сначала сделать его копию? Пожалуйста, ответьте при первой же возможности.

Пожалуйста, обязательно создайте минимально воспроизводимый пример. Обратите внимание, что все три слова важны: это должен быть только пример, вы не должны публиковать весь фактический код, а должны создать упрощенный пример, демонстрирующий вашу проблему. Кроме того, оно должно быть минимальным, т. е. не должно содержать ничего, что не является абсолютно необходимым для демонстрации проблемы. (Большинство проблем для начинающих можно продемонстрировать менее чем с помощью 5 коротких простых строк кода.) И это должно быть воспроизводимо, а это означает, что если я скопирую, вставлю и запущу код, я увижу ту же проблему, что и вы.

Jörg W Mittag 23.03.2024 19:03

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

Cary Swoveland 24.03.2024 19:37
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
1
3
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашей проблеме есть два момента:

  1. Структура данных

append по сути похож на cons, в том смысле, что он также должен добавлять элементы в базовый список. Однако в этом примере он фактически возвращает строку, не изменяя состояние объекта Pair.

Что вам действительно нужно сделать, так это append новый элемент в конец pair/list структуры. Для этого вам нужно пройтись по парам (при условии, что это действительный список), пока не найдете последний элемент, который должен быть null.

 def append(other)
  return false unless list?
  
  if cdr.nil?
    @value2 = other
  else
    cdr.append(other)
  end

  self
end

Также важно, чтобы вы возвращали «существующий» объект с помощью self, если хотите, чтобы puts был встроенным, как в вашем примере.

Возьмем, к примеру, следующий код:

b = cons(1, Pair.null)
c = cons(4, Pair.null)

puts b.append(c)

append здесь убедитесь, что создана следующая структура:

<Pair @value1=1, @value2=<Pair @value1=4, @value2=nil>>
  1. Распечатываем list

Теперь, чтобы распечатать список, нужно решить еще одну рекурсивную задачу (как и первая). Вам нужно просмотреть список пар, а также учесть различные случаи. Вот почему так важно поддерживать правильную структуру данных.

def to_s
  helper_to_s(true)
end

def helper_to_s(started = false)
  str = ""
  str += "(" if started
  str += "(" if started && car.is_a?(Pair)

  if car.is_a?(Pair)
      str += car.helper_to_s
  else
    str += car.to_s
  end

  if cdr.nil?
    str += ")"
  elsif cdr.is_a?(Pair)
    str += " "
    str += cdr.helper_to_s()
  else
    str += " . #{cdr})"
  end

  str
end

Нам нужен helper function, чтобы мы могли сообщить вызову рекурсии, когда нужно open(. Кроме того, нам также необходимо учитывать случай, когда у нас сразу есть вложенная пара. Наконец, благодаря нашей структуре данных мы можем определить, когда cdr не null, то есть это не pure list, в этом случае мы можем просто объединить . с конечной строкой, и она будет правильно отображаться при вызове to_s.

Если у вас есть дополнительные вопросы, обязательно ознакомьтесь с документацией по парам и спискам в документации по ракетке: https://docs.racket-lang.org/guide/Pairs__Lists__and_Racket_Syntax.html это действительно полезно.

Другие вопросы по теме