LINUX.ORG.RU

от @ugoday https://www.linux.org.ru/forum/development/17376931?cid=17400463

редполагается, что полученные навыки вы потом сможете перенести на любой язык (или написать свой). А практические задачи лучше решать на практических языках — CL и Clojure (которая сама может использовать все Java библиотеки, куда уж больше?).

значит Scheme мне не подходит, мне практические задачи решать.

Elidee
() автор топика

комментарий от @den73 https://www.linux.org.ru/forum/development/17376931?cid=17400658

Не понял, что тут с тобой случилось и почему ты не можешь отвечать

почему-то большен нет ссылки «ответить на это сообщение». Пришлось создать тему здесь.

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

Elidee
() автор топика

комментарий от @ugoday https://www.linux.org.ru/forum/development/17376931?cid=17400662

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

В программировании я не новичек, а вот с лиспами никогда не пересекался.

Elidee
() автор топика

комментарий от @lovesan https://www.linux.org.ru/forum/development/17376931?cid=17400766

Надо брать CL.

Технически, даже если потом работать на Clojure - учить и втыкать надо сначала все-равно в CL.

Scheme/Racket - это все учебные языки для ресерча в академии и студентоты. Накрайняк - для мелкого скриптинга (gnu guile).

Спасибо за ответ.С какой книги/тьюториала/гайда лучше начинать? Есть ли список проверенных книг?

Elidee
() автор топика

Почему-то не могу отправлять комментарии в ту тему

Вот почему

Ограничение на отправку комментариев: ★

vbcnthfkmnth123 ★★★★★
()
Последнее исправление: vbcnthfkmnth123 (всего исправлений: 1)

комментарий от @lovesan https://www.linux.org.ru/forum/development/17376931?cid=17400778

Вот чето есть, я не пробовал правда. Но вроде это известный лиспер писал

https://github.com/pokepay/aws-sdk-lisp/tree/master

Плюс, смотри вот тут: https://awesome-cl.com/

там есть некоторые библиотеки.

Как из схемы работать с базой данных? Тот же Postgres?

Куча ORM и всякого есть

итд

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

библиотека вроде есть, но она в статусе alpha, но по крайней мере хоть что-то.

А вот для clojure есть aws-api причем похоже от компании в которой работал создатель clojure.

Что еще больше удивило, оказывается для Aws Lambda можно использовать Clojure Writing AWS Lambda Functions in Clojure

Elidee
() автор топика

Ты не офигел? Скор для того и нужен, чтобы ты НЕ отправлял комментарии.

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

Если это мне - то я задал в теме вопросы разным людям. Будет невежливо оставить их ответы без какой-то обратной связи.

Elidee
() автор топика
Ответ на: комментарий от hibou

Согласен. Ведь сначала я мог оставлять комментарии в теме, а потом такая возможность исчезла. Приходится как-то разруливать эту ситуацию.

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

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

Racket родился как учебный, но нынче полнофункциональный язык общего назначения. Примерно как Паскаль был изначально учебный, а потом из него сделали Delphi.

Теперь по списку:

Есть ли на схеме библиотеки для AWS?

https://github.com/greghendershott/aws

Как из схемы работать с базой данных? Тот же Postgres?

https://docs.racket-lang.org/db/using-db.html Есть переиспользование соединений: https://docs.racket-lang.org/db/using-db.html .

Как из схемы читать данные из Kafka в avro формате?

https://github.com/Bogdanp/racket-avro

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

Неожиданно :).

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

Тогда у меня вопрос - в чем отличие того же Racket (или вообще scheme) от Common Lisp? Что их делает разными языками?

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

значит Scheme мне не подходит, мне практические задачи решать.

Нет ничего практичнее хорошей теории, но, как хотите. Ваша жизнь, ваши правила.

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

Тогда у меня вопрос - в чем отличие того же Racket (или вообще scheme) от Common Lisp? Что их делает разными языками?

В первую очередь — идеология: Анализ пользователей Common Lisp и Racket

На Common Lisp обычно получается чуть быстрее написать. Но намного сложнее получить гарантии надёжной работы. И принято документировать между строк кода.

В Racket же есть контракты (https://docs.racket-lang.org/guide/contracts.html), типизированные модули (https://docs.racket-lang.org/ts-guide/index.html), стандарт на документацию (https://docs.racket-lang.org/scribble/index.html).

Причём всё сделано не в стиле, принятом в C и Common Lisp, когда достаточно, чтобы библиотека работала в 90% случаев, а если что не так, то будет UB в C или отладчик в CL.

Если контракты, то с возможностью указать контракт типа «данная функция возвращает функцию от числа, которая всегда возвращает число не меньше переданного первого аргумента»:

(->i ([argument real?])
      [result (argument) (-> real? (>=/c argument))])

Если типизация, то система типов уровня Haskell, а не C++.

Если документация, то с возможностью вывода в HTML и TeX и возможностью вычислять во время формирования текста.

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

Если компиляция, то воспроизводимая. В CL все модули компилируются в одной виртуальной машине и процесс компиляции модуля может влиять на компиляцию следующего. В Racket компиляция каждого модуля в изолированной среде.

В недостатке — чуть ниже производительность (аналога declare unsafe из CL нет) и хуже отладчик.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от slew

Для этого пришлось бы движок править, фантазер.

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

Scheme мне не подходит, мне практические задачи решать

Для решения практических задач, конечно, нужно углубляться непосредственно в язык, на котором ты будешь их решать. Но кроме конкретных знаний об использовании конкретного языка нужны ещё общие, абстрактные знания о программировании как таковом (как устроены вычислительные процессы и как их можно организовывать), независимо от языка. И здесь уже, понятное дело, конкретный язык особого значения не имеет. Такие знания переносятся на любой язык, который ты уже освоил или захочешь освоить когда-нибудь. ROI просто зашкаливает %)

Такого рода материала полно как раз на схеме — Little/Seasoned/Reasoned Schemer, HTDP, SICP. Так сложилось исторически (тм).

Конечно, немножко схемы выучить придётся, но после кложи/CL это будет изи катка. Проще схемы только наскальная живопись.

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

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

Вот нет. То есть, конечно, «настоящий программист может программировать на Фортране на любом языке». Но в реальности язык определяет как минимум базовую абстракцию: байтовый массив для Си/Си++, список для лиспов, массив (многомерный) для APL/J/K, бесконечноый ленивый список для Haskell.

В этом смысле Racket также почти уникален, так как на него можно переносить код практически с любого языка не меняя семантики: семантика позволяет работать как с ленивыми списками в стиле Haskell, так и с указателями в стиле Си++.

В то время, как перенести на Си++ что-то вроде

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
fib = (fibs !!)

достаточно проблематично.

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

Всё ж зависит от материала. LoL тоже на С++ замучаешься переводить, но SICP даёт такую базовую базу, что её можно будет применять где угодно.

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

LoL тоже на С++ замучаешься переводить, но SICP даёт такую базовую базу, что её можно будет применять где угодно.

Взаимоисключающие утверждения. Часть SICP в C++ применить невозможно (макросы, лямбды), часть возможно, но вредно (рекурсия, функции как параметры). При этом такой базовой идеи C++ как итераторы в SICP вообще нет.

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

Часть SICP в C++ применить невозможно (макросы, лямбды)

Я про С++ знаю мало, но там же есть и то, и другое, разве нет?

вредно (рекурсия, функции как параметры)

Спорно. С чего бы это вредно?

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

Я про С++ знаю мало, но там же есть и то, и другое, разве нет?

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

Лямбды есть, но из-за отсутствия сборщика мусора также куча ограничений.

Спорно. С чего бы это вредно?

С того, что в Си++ вызов функции — это аппаратный вызов с использованием стека. Причём оптимизация хвостовых вызовов отсутствует. Поэтому если в Си++ написать, как принято в лиспах что-то вроде

int f(int n, int k)
{
   if (n) f(n-1, g(n, k)); else return k;
}

то это будет значительно медленнее, чем через нормальный for.

monk ★★★★★
()

На самом деле, не советую читать SICP – это очень плохая книжка, которую практически невозможно читать как книжку. Зато это очень хороший сборник рецептов и эссе на тему «структуры и интерпретации…», в этом смысле лучше ты не найдешь.

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

Еще вопрос про различия. Вот код на Racket:

> (list cons car cdr)
(#<procedure:mcons> #<procedure:mcar> #<procedure:mcdr>)

делает список из трех функций Почему в Common Lisp тот же код выдает ошибку?

> (list cons car cdr)

*** - SYSTEM::READ-EVAL-PRINT: variable CONS has no value
The following restarts are available:
USE-VALUE      :R1      Input a value to be used instead of CONS.
STORE-VALUE    :R2      Input a new value for CONS.
ABORT          :R3      Abort main loop
Break 1 [4]> 

при этом эти функции точно определены:

[6]> (cons 1 2)
(1 . 2)

Ведь даже в Go можно передать функцию как параметр по имени:

v1 := router.Group("/v1")
{
	v1.POST("/login", loginEndpoint)
	v1.POST("/submit", submitEndpoint)
	v1.POST("/read", readEndpoint)
}
Elidee
() автор топика
Ответ на: комментарий от buddhist

Насколько я помню, в SICP не определяется ни одного макроса.

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

И язык-как-данные там есть. Там где про метаязыки.

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

Почему в Common Lisp тот же код выдает ошибку?

Потому что в Common Lisp есть отдельно «переменная cons» и «функция cons». Можно писать так

(setf cons 1)
(cons cons cons) ; вернёт пару из двух единиц

(list cons car cdr)

В CL это будет

(list #'cons #'car #'cdr)

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

Кстати, в обратную сторону аналогично

Racket

; вызывает g с параметром x
(define (f g x)
  (g x))

CL:

; g - это переменная, а не функция, поэтому funcall
(defun f (g x)
  (funcall g x))
monk ★★★★★
()
Ответ на: комментарий от monk

и #’ и funcall выглядит как inconsistency в языке. Какая разница что в переменной. Есть какая-то причина почему так сделали?

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

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

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

В результате всё равно утечка потенциально возможна. Например, если в (labels ((list ...)) (m ...)) макрос m использует функцию list, то будет использоваться локально определённая. Поэтому в CL просто просят не перекрывать стандартные функции локальными и не использовать в макросах что-то кроме стандартных функций или функций из пакетов, не предназначенных для пользователя библиотеки.

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

Вот это как раз пример того, где одна и та же задача в CL и Scheme/Racket решена кардинально по-разному. В CL сделано так, чтобы было проще отлаживать. В Scheme/Racket сделано так, чтобы вызов макроса гарантированно делал то, что предполагал разработчик макроса.

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

Лямбды есть, но из-за отсутствия сборщика мусора также куча ограничений.

Однако, после SICP у человека будет в принципе понимание «что такое лямбды и зачем их придумали». Это важный педагогический результат.

то это будет значительно медленнее, чем через нормальный for.

Зато значительно более выразительно. В итоге, с правильной подготовкой мы получим более образованного специалисты с лучшим кругозором, а не ПТУшника, который выучил парочку приёмов и собирается прожить всю жизнь на этом интеллектуальном багаже.

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

Я бы свёл всё к: scheme это лисп, ориентированный на разработку сверху-вниз, а CL — снизу вверх. А дальше кому что больше на душу ложится.

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

До макросов я еще не дошел, поэтому не понимаю что такое «негигиеничный». Но похоже что второй namespace был введен для решения проблемы порожденной гибкостью языка. Хотя все равно странно иметь две переменные с одинаковым именем и при этом в одной из них данные, а в другая - функция.

Elidee
() автор топика
Ответ на: комментарий от ugoday

Однако, после SICP у человека будет в принципе понимание «что такое лямбды и зачем их придумали». Это важный педагогический результат.

Лямбы же практически в любом языке есть. Или в тут они какие-то особенные?

Elidee
() автор топика
Ответ на: комментарий от ugoday

Увы, но нет.

В обоих отлично работает как сверху вниз, так и снизу вверх. Но в CL когда регулярно натыкаешься на невозможность гарантировать корректную работу при любых действиях пользователя, то постепенно начинаешь писать библиотеку в стиле «вот документация как пользоваться, если кто-то сделал что-то не то, сам виноват». И при использовании библиотек, соответственно, периодически приходится лазить в их исходники. Зато если разработчик библиотеки что-то забыл, можно переопределить почти что угодно в коде, использующем библиотеку.

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

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

Хотя все равно странно иметь две переменные с одинаковым именем и при этом в одной из них данные, а в другая - функция.

Функции - это не переменные. Ещё такое же имя может быть у класса, у типа, …

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

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

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

Я исхожу из логики «если есть, но неудобно и сложно, значит нету». В пределе defmacro и #define делают одно и то же, но в одном случае макропрограммирование считается удобным подспорьем, а в другом — кошмаром, который следует избегать любой ценой. И эти практические выводы гораздо важнее теоретической применимости.

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

Ну да, а переменная - именованная область в памяти. Но ведь и функция занимает некую область в памяти и имеет имя. Как тебе такое, Илон Маск??

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

Я про синтаксис. В Racket

(define a (...)) ; а здесь станет классом/значением/функцией/...

В Си++

int a(...) ... // функция

int a = ... // переменная

class a { ... } // класс

typedef a // тип
monk ★★★★★
()
Ответ на: комментарий от Elidee

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

monk ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.