LINUX.ORG.RU

Так и писать:

(defun f (obj)

передача копированием происходит только для очень простых объектов, таких как числа, либо при явном копировании (copy-list, copy-alist, copy-tree, copy-seq, alexandria:copy-array, ...).

quasimoto ★★★★ ()
Ответ на: комментарий от quasimoto

А как тогда передать копию объекта? Нужно для каждого уникального объекта писать и вызывать функцию копирования? Или компилятор умеет сам создавать копии объектов бит в бит.

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

Сформулирую чего я хочу. Поведение как в С++: f(obj) - копия объекта, f(&obj) - ссылка.

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

На русском языке в прошлом году вышел хороший перевод книги Пола Грэма «ANSI Common Lisp».

dave ★★★★★ ()
Ответ на: комментарий от Alex-Alex

Смотря какие объекты. Для некоторых примитивных типов есть ad-hoc функции — http://www.nhplace.com/kent/PS/EQUAL.html, например для структур:

(defstruct ref /)

(defun f (obj)
  (format t "f.1: ~S~%" obj)
  (setf (ref-/ obj) 0)
  (format t "f.2: ~S~%" obj))

(let ((obj (make-ref :/ 5)))
  (format t "1.1: ~S~%" obj)
  (f obj)
  (format t "1.2: ~S~%" obj))

; 1.1: #S(REF :/ 5)
; f.1: #S(REF :/ 5)
; f.2: #S(REF :/ 0)
; 1.2: #S(REF :/ 0)

(let ((obj (make-ref :/ 5)))
  (format t "2.1: ~S~%" obj)
  (f (copy-ref obj))
  (format t "2.2: ~S~%" obj))

; 2.1: #S(REF :/ 5)
; f.1: #S(REF :/ 5)
; f.2: #S(REF :/ 0)
; 2.2: #S(REF :/ 5)

Для CLOS вообще — http://stackoverflow.com/q/11067899/1337941.

quasimoto ★★★★ ()
Ответ на: комментарий от quasimoto

Лол, какая куча КОСТЫЛЕЙ вместо плюсового f(obj).

anonymous ()
Ответ на: комментарий от anonymous

Лол, какая куча КОСТЫЛЕЙ вместо плюсового f(obj).

Лол, дурашка, так в лиспе никто не далает. Просто ТСу нужно было, как в цепепе вот и дали ему решение. Лол.

anonymous ()
Ответ на: комментарий от Alex-Alex

Поведение как в С++: f(obj) - копия объекта, f(&obj) - ссылка.

То есть нужен макрос my-defun чтобы писать (my-defun f ((ref x) (copy y))? Тогда нужно запомнить сигнатуру f по части ref/copy и сделать соответствующий (call f x y) — пусть смотрит на эту сигнатуру и пишет код который смотрит на объект, пытается сделать гарантированную ссылку или копию и бросает исключение если не может.

quasimoto ★★★★ ()
Ответ на: комментарий от anonymous

Во первых непонятно, как в лиспе тогда пишут в функциональном стиле, когда все объекты CLOS передаются по ссылке. И как решить такую задачу: передать в функцию копию произвольного объекта, изменить несколько слотов и вернуть этот объект.

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

И как решить такую задачу: передать в функцию копию произвольного объекта, изменить несколько слотов и вернуть этот объект.

Сделать копию, потом передать, изменить и вернуть. В чем проблема?

anonymous ()
Ответ на: комментарий от anonymous

Понял как спросить. Есть ли в Lisp обобщенный копирующий конструктор по умолчанию, который умеет копировать инстанс объекта бит в бит, или копирующий конструктор мне надо реализовывать самому для каждого моего класса? Типа

(defmetod copy-obj ((obj my-obj)))

(f (copy-obj my-obj)) - передача объекта по значению

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

Есть ли в Lisp обобщенный копирующий конструктор по умолчанию, который умеет копировать инстанс объекта бит в бит

Лол, ты чо, «лисп работает по-другому». А паттерн «прототип» — это, конечно же, выдумка быдложабоархитекторов и прочих жидомасонов и поэтому нинужен.

или копирующий конструктор мне надо реализовывать самому для каждого моего класса?

Дык в этом и суть лиспа, что МОЖНОЗДЕЛОТЬ. Кстати, если не секрет, почему ты решил податься в лисперы? Начитался ЛОРа/харкача?

anonymous ()
Ответ на: комментарий от anonymous
(defstruct btree l r)

(defun copy/btree (obj)
  (if (typep obj 'btree)
      (make-btree :l (copy/btree (btree-l obj)) :r (copy/btree (btree-r obj)))
      obj))

не знаю чем тут поможет плюсовое f(obj).

А простая копия структуры в лиспе делается в месте вызова с помощью (f (copy-struct-name obj)) вместо декларации bitcopy в месте определения функции и перепоручения делать copy в месте вызова компилятору (как оно в плюсах) — стратегия копирования может быть разной (просто copy-btree или полное copy/btree, например), её выбирает «клиент».

quasimoto ★★★★ ()
Последнее исправление: quasimoto (всего исправлений: 2)
Ответ на: комментарий от anonymous

Хочу познакомиться с функциональным языком. Lisp мне показался самым простым и система установки библиотек quicklisp очень сильно помогает. Имею некоторы опыт программирования на С++.

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

Хочу познакомиться с функциональным языком.

Ну, хорошо. Откуда желание познакомиться с функциональным языком?

И, кстати, почему не Python/Ruby/Haskell/Scala/JavaScript? Ведь это всё тоже функциональные языки.

anonymous ()
Ответ на: комментарий от quasimoto

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

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

Имею некоторы опыт программирования на С++.

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

anonymous ()
Ответ на: комментарий от Alex-Alex

копирующий конструктор мне надо реализовывать самому для каждого моего класса?

yup

anonymous ()
Ответ на: комментарий от anonymous

Haskell слишком замороченный. Там очень плохо развита диагностика ошибок, очень сложно понять в каком месте возникла ошибка. А так, влияние ЛОРа по части Lisp имеет место.

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

А так, влияние ЛОРа по части Lisp имеет место.

Кошмар. Не поддавайся этому влиянию.

dave ★★★★★ ()
Ответ на: комментарий от Alex-Alex

А так, влияние ЛОРа по части Lisp имеет место.

Лол, ну, я так и думал.

Т.е. тебе нужен не «функциональный язык», а модный, нонконформистский и илитарный, про который ты начитался на ЛОРе. Что ж, с одной стороны жалко, что ты потратишь некоторую часть молодости на изучение в общем бесполезной и бесперспективной технологии. Лучшим программистом это тебя тоже не сделает.

Зато, может быть, на своей шкуре поймёшь, что надо поменьше доверять ЛОРовским троллям, и побольше думать головой. Удачи.

anonymous ()
Ответ на: комментарий от anonymous

Я хочу составить собственное мнение. Познакомиться с языком, еще не значит писать на нем всю жизнь. Многие вещи в Lisp мне очень нравяться: emacs, slime, quicklisp.

Alex-Alex ()
Ответ на: комментарий от dave

Той древней? Или какое-то новое издание?

anonymous ()
Ответ на: комментарий от anonymous

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

Хотя Racket из них более менее красив и интересен, особенно typed.

anonymous ()
Ответ на: комментарий от Alex-Alex

Lisp - не функциональный язык. Смотри на Haskell, F# или Scala.

anonymous ()
Ответ на: комментарий от anonymous

устаревший методики

Примеры можно? Что там устарело, например по сравнению с питоном?

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

Ты хочешь копировать объекты, и хочешь писать в стиле ФП. Здесь есть противоречие. Когда пишут в стиле ФП, то данные обычно разделяют и не меняют их, да и передают их по ссылке (тут термины разные бывают, но в общем, лисп передает как надо). По умному такие данные называются persistent purely functional data.

Тут есть одна проблема с лиспом. Если ты не знаешь, как работать с такими данными, то Common Lisp тебя этому не научит, т.е. не будет бить по рукам, если ты сделаешь что-то не так. CL - очень гибкий и практичный инструмент, он послушно будет делать то, что ты ему скажешь. А потому как первый, как второй или даже как третий язык совершенно непригодный (хотя бывают исключения). Для обучения нужны более жесткие и менее компромиссные языки. В идеале, это даже могут быть языки одной парадигмы (haskell, smalltalk, си).

dave ★★★★★ ()
Ответ на: комментарий от Alex-Alex

Есть ли в Lisp обобщенный копирующий конструктор по умолчанию, который умеет копировать инстанс объекта бит в бит

Нет

или копирующий конструктор мне надо реализовывать самому для каждого моего класса

Да

vasily_pupkin ★★★★★ ()
Ответ на: комментарий от anonymous

Да, той самой. Стандарт не менялся, хотя расширения добавляются, а реализации совершенствуются.

dave ★★★★★ ()
Ответ на: комментарий от anonymous

Haskell неоправданно переусложнен. К тому же там нет объекто-ориентированной парадигмы, и как следствие невозможность отделение интерфейса от реализации.

Alex-Alex ()
Ответ на: комментарий от vasily_pupkin

или копирующий конструктор мне надо реализовывать самому
для каждого моего класса

Да

Нет. Можно написать один раз и это будет работать для всех классов. Работа тривиальная, но что-то пока ни разу не было в этом необходимости.

archimag ★★★ ()
Ответ на: комментарий от archimag

Ну не будет же. Иначе бы было в стандарте :] Будет работать для классов простых как валенок

vasily_pupkin ★★★★★ ()
Ответ на: комментарий от Alex-Alex

невозможность отделение интерфейса от реализации

ликодлань. в каком ещё языке тебе из коробки предложат работать со строками через интерфейс моноида?

как следствие

кто тебе сказал, что инкапсуляция неотделима от ООП?

jtootf ★★★★★ ()
Ответ на: комментарий от Alex-Alex

плохо развита диагностика ошибок, очень сложно понять в каком месте возникла ошибка

можно пример кода, в котором у тебя были проблемы с диагностикой ошибок?

jtootf ★★★★★ ()
Ответ на: комментарий от Alex-Alex

В плюсах стратегия тоже может быть разной

Это как? Пусть будет template <typename T> tree { ... и два вида копирования — shallow и deep. Писать два перегруженных/шаблонных по отношению к copy_strategy = shallow_copy или deep_copy (enum или пустые структуры) конструктора tree(tree<T> &)? Их можно написать? Как это скажется на обычном вызове f(tree<T>)? Всё равно проще сделать нормальные методы и выбор в месте вызова.

quasimoto ★★★★ ()
Ответ на: комментарий от Alex-Alex

А почему это не включили в стандарт?

А зачем? На CL так не пишут.

archimag ★★★ ()
Ответ на: комментарий от Alex-Alex

Понял как спросить. Есть ли в Lisp обобщенный копирующий конструктор по умолчанию, который умеет копировать инстанс объекта бит в бит, или копирующий конструктор мне надо реализовывать самому для каждого моего класса?

Нет. В CLOS (вернее, в metaobject protocol, на котором CLOS написан) есть достаточное количество интроспекции, чтобы разобрать объект и собрать его копию. Это можешь написать в качестве начального знакомства с MOP. Для последовательностей есть copy-seq. Тип объекта определяется в рантайме.

mv ★★★★★ ()
Ответ на: комментарий от Alex-Alex

Зато в F# и Scala ООП на полную катушку. Впрочем, твое утверждение неверно. ООП не связано напрямую с разледением интерфейса от реализации. В том же Haskell есть и модули, и тайпклассы.

anonymous ()
Ответ на: комментарий от archimag

Нет. Можно написать один раз и это будет работать для всех классов. Работа тривиальная, но что-то пока ни разу не было в этом необходимости.

Мне надо было. Для последующих деструктивных действий над копией при параллельно здравствующем оригинале.

mv ★★★★★ ()
Ответ на: комментарий от vasily_pupkin

Ну не будет же. Иначе бы было в стандарте :] Будет работать для классов простых как валенок

Вообще-то работает с любой объектной системой, написанной на MOP.

mv ★★★★★ ()
Ответ на: комментарий от mv

Ладно, видно, что до MOP я еще не дозрел. Есть еще вопрос, как экспортировать из пакета символы всех акцессоров класса?

Я надеялся что :export :class-name будет достаточно, но не получается.

Alex-Alex ()
Ответ на: комментарий от quasimoto

Можно использовать паттерн «стратегия». В книжке Александреску есть глава про это.

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

Ладно, видно, что до MOP я еще не дозрел. Есть еще вопрос, как экспортировать из пакета символы всех акцессоров класса? Я надеялся что :export :class-name будет достаточно, но не получается.

Нет в CLOS акцессоров. Есть обобщённые функции и их специализации.

mv ★★★★★ ()
Ответ на: комментарий от mv

Хорошо. Как экспортировать все обобщенные функции доступа к слотам класса чохом? Утомительно их всех перечислять в :export.

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

Напиши макрос-обёртку над defclass, который будет создавать класс и экспортировать засвеченные в нём дженерики.

mv ★★★★★ ()
Ответ на: комментарий от mv

А что еще никто не написал? Или опять на лиспе так не пишут? Вроде обычная ситуация определем класс в одном пакете, а используем в других.

Alex-Alex ()
Ответ на: комментарий от Alex-Alex

Или опять на лиспе так не пишут?

Некоторые так делают, но я считаю это дурным тоном. Секция :exports пакета определяет публичный интерфейс. Если экспорты будут разбросаны по коду, то это затруднит его чтение и понимание.

archimag ★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.