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

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