LINUX.ORG.RU

DrRacket and elisp окончательно запутался

 ,


0

3

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

#lang racket
(define *distance-lst* (list 1 2 3 4 5 6))

(define *A-distance* 3)
(define *left-A-lst* '())

(define d-lst (length *distance-lst*))
(define *output-lst* '())
(define (slice input-lst a output-lst)
  (if (< (first input-lst) a)
      (slice (cons (first input-lst) output-lst)
             a
             (set! input-lst (rest input-lst)))
      output-lst))
     
;;(define (split-lst lst-input a lst-output)
;  (if (< (first lst-input) a)
 ;     (split-lst (set! lst-input (rest lst-input))
  ;                     a
   ;                    (set! lst-output
    ;                         (cons
     ;                         (first lst-input) lst-output)))
 ; lst-output))

(slice *distance-lst* *A-distance* *left-A-lst*)

и вот на elisp и работает как надо, задолбало, что не так не могу понять эту ракету

(defun slice (input-lst a output-lst)
(if (< (car input-lst) a)
(slice (cdr input-lst) a (push (car input-lst) output-lst))
output-lst))

(nreverse (slice '(1 2 3 4 5 6) 5 '()))

(define A-distance 3)

(< (first input-lst) a)

так это никакая не дистанция, а скорее порог по значению

(set! input-lst (rest input-lst))

щито это? зачем что-то сетить если потом это не использовать? и зачем rest для output-lst если

возвращает левую часть

BOSS-NIGGER
()

режет лист на две части и возвращает левую часть

В емаксе же есть seq-take-while (если я правильно понял, что ты хочешь делить по условию).

В ракетке slice неудачное название, там такой встроенный есть. А вообще в srfi-1 есть take-while.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

В емаксе же есть seq-take-while (если я правильно понял, что ты хочешь делить по условию).

seq-take-while спасибо за функцию, буду знать.

В ракетке slice неудачное название, там такой встроенный есть. А вообще в srfi-1 есть take-while.

Ракета в голову никак не лезет, GUI кое-как получались и то если бы не monk они бы вообще не получились. Вобщем крик души. Я пишу програмки для своих нужд.

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

Я-то ракетку и схему не люблю. Слишком они рафинированно-академические. Многословно строгие, как Паскаль. То ли дело CL, язычище настоящих негигиеничных суровых мужиков!

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Я-то ракетку и схему не люблю. Слишком они рафинированно-академические. Многословно строгие, как Паскаль. То ли дело CL, язычище настоящих мужиков!

Ну да, а борщелисп прям образец краткости. Такие-же-многословные-и-подробные-идентификаторы.

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

Такие-же-многословные-и-подробные-идентификаторы

Проблема не в длине а в количестве слов, которые нужно «сказать» чтобы что-то сделать. Пример ТСа, в CL решается элементарно и прямолинейно через loop .. while .. collect.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

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

Virtuos86 ★★★★★
()
Ответ на: комментарий от no-such-file

То ли дело CL, язычище настоящих негигиеничных суровых мужиков!

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

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

увидеть бы идиоматический код для решения задачки (сомневаюсь, что у ТС он такой).

А, что такое идиоматический код?

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

это сахарок

Ну так-то всё что выше Машины Тьюринга это сахарок. Главное, что из коробки есть. Или нужно таки до tagbody/go дойти?

идиоматический код для решения задачки

Вполне идиоматично - обходим через рекурсию, по дороге консим и в конце nreverse. В CL, если без loop, то будет тоже самое только без рекурсии, а на dolist. Есть ещё вариант find + subseq.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от saufesma

увидеть бы идиоматический код для решения задачки (сомневаюсь, что у ТС он такой).

А, что такое идиоматический код?

Типовой код, написанный с использованием best practices выбранного языка программирования. Правильнее сказать, идиоматичный, я что-то не то ляпнул там.

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

увидеть бы идиоматический код для решения задачки (сомневаюсь, что у ТС он такой).

Пока, тружусь, самому охота побыстрей сделать, да в ракете запутался. Дай время.

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

Если я правильно понял, что автору надо (выбрать все элементы меньше a), то будет просто (filter (lambda (x) (< x a) lst). Или сокращённо (filter (</c a) lst).

В переменных автора:

(define *left-A-lst* (filter (</c *A-distance*) *distance-lst*))
monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от no-such-file

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

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

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

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

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

Есть loop и ради однострочника писать функцию не хочется.

 (loop for i on lst while (pred (car i)) collect (car i) into left finally (return (values left i)))

вернёт искомые два списка

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

(for/first ([n (in-naturals)]
            [i (in-list ...)] ; ну или в какой другой последовательности
            #:when (pred i))
  n)
monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от Virtuos86

Дали бы эталонную библиотечную функцию, и все дела

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

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

(loop for i on lst while (pred (car i)) collect (car i) into left finally (return (values left i)))

Сразу видно ракетчика. Не нужно стесняться в выражениях, тут можно по царски называть вещи нормальными именами и не выёживаться каждый раз с (car i):

(defun partition (list test)
  (loop
   for right on list
   and this in list
   while (funcall test this)
   collect this into left
   finally (return (values left right))))
no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Шта? Вот Rust это нормальный язык? Компилируется в машкод, поэтому не проблема каждому пилить свой лисапед с квадратными колесами, но при этом достаточно резво едущий. Почему там у векторов есть много чего, в том числе и всевозможные split*?

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

Вот Rust это нормальный язык?

Ты ещё спрашиваешь? Нет, конечно, это эталонная наркомания. Ты б ещё brainfuck вспомнил.

Почему

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

no-such-file ★★★★★
()
Ответ на: комментарий от Virtuos86

Падажжи, я там глянул split, так это же совсем не то, ведь

Returns an iterator over subslices separated by elements that match pred

В CL не нужно в принципе. Чтобы разделить на два вектора нужно потом аллоцировать память на эти два вектора и скопировать через итераторы. Это ровно тоже что сделают в CL find + subseq.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

А могли бы просто возвращать ленивый итератор, чтобы не мучать гц лишний раз.

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

Не могу назвать Rust нормальным языком. Перегруженный синтаксис, очень сложный инструментарий с множеством не явных особенностей. Чтобы писать на нём нормально надо долго и упорно зубрить учебник. Показатель скорее плохого языка.

silver-bullet-bfg ★★
()
Ответ на: комментарий от silver-bullet-bfg

Ясно. То, от чего комитет С++ рад бы отказаться, да не может из-за легаси, ты предпочитаешь современным альтернативам.

move по дефолту вместо копирования избавляет от проблем с владением и move forwarding.

Разность *mut, mut и &mut очевидна и необходима, потому что указатель на мутабельное значение, мутабельное значение, и ссылка на мутабельное значение просто обязаны отличаться, они буквально разные. Про указание типов я вообще не въехал, у тебя есть альтернативы? Голанговские круглые скобки не предлагать.

Siborgium ★★★★★
()
Ответ на: комментарий от no-such-file

Там по 2 версии обычно методов, потому что Vec наследует методы от слайсов (там своя магия приведения типов), которые есть ссылочный тип данных, поэтому их методы логично возвращают срезы же. Срезы могут быть мутабельные и иммутабельные. Документация к методам от слайсов, но в примерах видно, что и к векторам применимо. Тебе надо split_mut смотреть или `split_off`. Сейчас неудобно отвечать.

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

Ясно. То, от чего комитет С++ рад бы отказаться, да не может из-за легаси, ты предпочитаешь современным альтернативам.

Например? Ну и да, я не считаю С++ за язык хотя бы с удовлетворительным синтаксисом.

move по дефолту вместо копирования избавляет от проблем с владением и move forwarding.

Это не явное поведение

Разность *mut, mut и &mut очевидна и необходима,

Спроси у любого, кто не погружен в язык. Пусть ответят. Очевидный и явный синтаксис тот, где не надо лезть в документацию, его понятно по общей семантике. Это не очевидно и не явно, если ты не в курсе семантики Rust или С++

Про указание типов я вообще не въехал, у тебя есть альтернативы? Голанговские круглые скобки не предлагать.

С ходу не скажу. Но такой как в раст подход мне не удобен и для меня не читаем, как и для любого нормального человека. Скорее тут что-то нужно похожее на аннотациия сложных типов в Haskell

silver-bullet-bfg ★★
()
Последнее исправление: silver-bullet-bfg (всего исправлений: 2)
Ответ на: комментарий от Virtuos86

Тебе надо split_mut смотреть

Без разницы. Это ж чисто растовские костыли, суть работы у них одинаковая.

Returns an iterator over mutable subslices separated by elements that match pred

Да и не удивительно. Вряд ли уместно выполнять там неявное выделение памяти. В целом же, всё это эквивалентно find из CL. Только в CL получают индекс, а дальше уж как хочешь - то ли по оригинальному массиву ходи, то ли копии делай. Просто изначальная задача у ТСа была именно в получении копии и именно списка. Для этого эффективнее собирать элементы за один проход, а не делать отдельно find и отдельно subseq в 2 прохода.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от Siborgium

Про указание типов я вообще не въехал, у тебя есть альтернативы?

Вопрос несколько глубже, чем ты наверное думаешь. Дело не в том, есть ли альтернативы, а в том, возможны ли лучшие альтернативы? Судя по тем мучениям, которые испытывают авторы языков пытаясь как-то просто и понятно это сделать, и как у них из этого получается всё сложно и заморочено, можно сделать вывод, что это в принципе невозможно, потому что человек слишком слабоумен и не в состоянии воспринимать такие вещи натурально и просто. Слишком уж всё это контринтуитивно. Нет, конечно в науке такого сложного тоже много, современная физика и математика также не доступна обывателю. Но разница тут в том, что науке человек может посвятить всю жизнь, натренировать свой мозг на понимание специальных закорючек и правил работы с ними ради великой цели, ради постижения непостижимого. А раст это же просто один из язычков, факультативный, необязательный инструмент. Ради чего же приносить себя в жертву? Так вот пока не появятся задачи такой сложности, такого объёма, что без тех средств которые дают идейно-сложные языки вроде раста никак нельзя справится, до тех пор всё это будет лишь интеллектуальной игрушкой, теорией ради теории для тех, кому некуда девать своё время и для тех, кто посвятил жизнь расту как вещи в себе (т.е. авторов, которые носятся со своим детищем и примкнувших к ним фанатичных апостолов нового программирования).

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Согласен на все 100%. Большая часть задач просто не требует Rust. А его применение не оправдано ничем. Ну вот нужен мне простой REST API, который кроме CRUD ничего не умеет. Сделав его на Rust я: 0. подведу под монастырь бизнес, надо ещё найти таких наркоманов как я; 1. лишаю проект будущего, т.к. дешевле переписать это всё, чем тащить дальше с собой; 2. делаю дорогим развитие, т.е. могу забыть о интенсивном развитии; 3. получаю сомнительные в рамках задачи киллер-фичи, которые собственно никому кроме меня и не нужны. Вопрос - тогда зачем оно надо?

silver-bullet-bfg ★★
()
Ответ на: комментарий от saufesma

В этой портянке можно раст с успехом заменить на обшелисп/ракетку/цацкель, и смысл особо не поменяется. Одна разница, Раст еще молод, и для него не всё так однозначно.

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

Если тебе нравится ржавчина ну и пиши на ней, никто не запрещает. Главное чтобы то, что написал клиентам нравилось. Делов-то. А я на лиспосраче как нибудь.

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

можно раст с успехом заменить на обшелисп/ракетку/цацкель, и смысл особо не поменяется

Конечно, это касается любого концептуально сложного языка, в частности всяких ML-ей, включая и Haskell. А вот с лиспом не так, лисп простой как полено в своих принципах, так что эти принципы можно объяснить даже первокласснику, как 2+2.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

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

saufesma
() автор топика
Ответ на: комментарий от no-such-file

А вот с лиспом не так, лисп простой как полено в своих принципах, так что эти принципы можно объяснить даже первокласснику, как 2+2.

Да? А среди студентов считается одним из самых сложных (сложнее разве что Форт).

Покажешь хоть одного первокласcника, который сможет объяснить как работает:

(defmacro once-only ((&rest names) &body body)
  (let ((gensyms (loop for n in names collect (gensym))))
    `(with-gensyms (,@gensyms)
      `(let (,,@(loop for g in gensyms
                      for n in names
                      collect ``(,,g ,,n)))
        ,(let (,@(loop for n in names
                       for g in gensyms
                       collect `(,n ,g)))
           ,@body)))))
monk ★★★★★
()
Ответ на: комментарий от no-such-file

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

Про последнее: угадаешь, чему равен результат

(iter (with x = 3)
      (for el in '(1 2 3))
      (setq x 1)
      (reducing el by #'+ initial-value x))
monk ★★★★★
()
Ответ на: комментарий от saufesma

даёшь клиенту свое творение на испытания, клиент соглашается/не соглашается

В проектах где я участвую у меня с владельцами бизнеса сложились доверительные, дружеские отношения основанные на долговременном сотрудничестве. Поэтому таких проблем в принципе нет. Т.е. «испытания» провожу либо я сам, либо сообщаю QA отделу, что пора мучать.

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

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

Покажешь хоть одного первокласcника, который сможет объяснить как работает

Ты ничего не понял. Разумеется даже на самых простых принципах, если они позволяют композицию, можно, постепенно углубляясь, делать сложные вещи. Но это будет очень подробно, многословно и неэлегантно. Что как раз и демонстрирует твой пример. Сравнивать концептуально сложные языки с лиспом, всё равно что сравнивать сложный матан с естественным языком. Уравнение Шрёдингера на этом матане записывается одной строчкой, но понять его могут не только лишь все. А вот на русском тоже самое рассказать и объяснить вполне возможно любому проходимцу без специальных знаний закорючек.

Посмотри на это с другой стороны. Вот есть ядро линукс, сложная программа на миллионы строк, написанная на очень простом языке. Объём её однако так велик, что нет ни одного человека, который может осмыслить весь этот код как единое целое и «знать» его до последней точки. Предположим что мы придумаем какой-то хороший язык, так что на нём всю эту сложную программу можно будет выразить в 10к строк. Казалось бы такой объём для одного человека уже посилен. Так вот мой тезис в том, что сложность программы при этом не уменьшится и количество усилий для её понимания тоже, поэтому осмыслить эти 10к всё равно не получится, а язык будет неизбежно сложным настолько, что для осмысления даже одного выражения нужно будет медитировать пару месяцев, как над пониманием сложной математической теоремы.

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

Haskell на порядок проще: у любой функции только один аргумент и только один результат

А ещё там ленивость, АТД, монады и чёрт в ступе.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

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

Спорный тезис. Например, для любой программы на Си на 10к строк будет соответствующая программа на более простом зыке ассемблера на 100к строк. И понять её будет намного сложнее, чем программу на Си.

Вообще, понимание упрощается, если язык позволяет явным образом описывать высокоуровневые концепции, не вдаваясь в подробности реализации. Например, в CLOS половина паттернов Java/C++ становятся очевидными однострочниками. Кода становится меньше и понимать его проще.

Не требуется осознавать сущности сразу целиком во всей их полноте.

На «простых» языках их вообще часто не получается осознать, если добрый автор не написал рядом комментарий типа /* реализация хеш-таблицы */.

А ещё там ленивость, АТД, монады и чёрт в ступе.

В Haskell ленивость везде, в лиспе выборочная ленивость через макросы (поэтому глядя на код, нельзя гарантировать что именно выполнится и что именно не выполнится).

АТД есть везде. Где-то описывается сложнее (union + struct в Си), где-то проще (Haskell, Lisp).

Монады не сложнее лиспового loop.

Чёрт в ступе скорее в лиспе, когда кто-нибудь начинает трогать таблицу чтения.

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

для любой программы на Си на 10к строк будет соответствующая программа на более простом зыке ассемблера на 100к строк

Несколько сомнительно, что будет такая пропорция, но не суть. Ассемблер сложнее Си в том смысле, что нужно учитывать оптимизацию под процессор и память. Если отбросить такую оптимизацию, и переписать программу «в лоб», то будет всё очень просто, аж до изжоги.

понимание упрощается, если язык позволяет явным образом описывать высокоуровневые концепции, не вдаваясь в подробности реализации

Ты так и не понял о чём вообще речь. А она не про сложность понимания алгоритма, паттерна и т.д., а про сложность понимания смысла отдельного выражения как такового. Это как иероглифы в китайском, которые имеют 100500 смыслов, так что текст можно понять и так и этак и всё это одновременно будет правильным пониманием. Те же монады уже как только не объясняли. Спроси на ЛОРе что такое монада, получишь 100500 разных ответов. И все правильные, разумеется.

Мы вообще примитивные обезьяны и мозг наш миллионы лет эволюционировал только для того чтобы эффективно жрать и трахаться. Он вовсе не предназначен для постижения мира. Единственный чит который нам помогает, это способность к обобщению, но и она всего лишь продолжение эволюционно значимого поведения, а не магическая способность через обобщение постичь всё. В физике она как-то работала пока мы не докопались до электрона, который понять мы не можем принципиально и поэтому городим костыли в виде принципа дополнительности и т.п. пытаясь как-то вместить сложность в рамки нашего понимания. И в программировании происходит тоже самое. Пока мы складывали 2+2 и писали хеловорды, простых языков было достаточно. Потом стали городить паттерны, пытаясь обуздать сложность. И вот мы дошли до таких пределов, где всё это больше не работает. Попытки обобщать дальше оканчиваются уродливыми костылями вроде Rust и заоблачным матаном вроде Haskell. Очевидно что существуют какие-то фундаментальные проблемы мироустройства, которые мы не понимаем и не осознаём даже, а тычемся как слепые пытаясь из говна и палок слепить машину для перемещения за грань реальности. В итоге у нас даже не 2 языка, как в физике, а 100500 и все говно, т.к. для чего-то да не подходят.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 5)
Ответ на: комментарий от no-such-file

Если отбросить такую оптимизацию, и переписать программу «в лоб», то будет всё очень просто, аж до изжоги.

Вы действительно считаете, что отслеживание логики программы по cmp/jz так же просто, как и по if (…) { … } ? Не говоря уж про арифметику.

а про сложность понимания смысла отдельного выражения как такового

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

Те же монады уже как только не объясняли. Спроси на ЛОРе что такое монада, получишь 100500 разных ответов. И все правильные, разумеется.

Зачем знать что это? Достаточно знать, как это использовать. Также как понятие special operator в лисп. Или тот же loop (кстати, фактически, монада).

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

… Или тот же loop (кстати, фактически, монада).

А кстати. Объясни монаду на примере loop-а, плз.

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

А вот с лиспом не так, лисп простой как полено в своих принципах, так что эти принципы можно объяснить даже первокласснику, как 2+2.

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

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

Объясни монаду на примере loop-а

(loop 
   for i in '(5 8 9)
   collect (+ i 5))

==

do
  i <- [5, 8, 9]
  return $ i+5
(loop 
   for i from 1 to 10
   when (evenp i)
   collect i)

==

do
  i <- [1..10]
  guard $ even i
  return i
monk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.