LINUX.ORG.RU

Код который не могу написать на common lisp

 , ,


0

3

Emacs lisp code

(mapcar (lambda (chr) 
          (if (eql chr ?.) 
              ?. 
              (- chr ?0))) 
        "123.45")
;; => (1 2 3 46 4 5)  ; . is 46 in ASCII 

Lispworks doesn't go.

Может кто-нибудь сможет перевести этот код на общий Лисп?

Aaa, наверное так

(map 'list '#(lambda (chr) 
          (if (eql chr ?.) 
              ?. 
              (- chr ?0))) 
        "123.45")
;; => попробовать не могу сейчас(1 2 3 46 4 5)  ; . is 46 in ASCII 



Последнее исправление: saufesma (всего исправлений: 3)

В переводе на CL, это будет не вот это извращение с лямбдами, а вот так:

(loop :with z = (char-code #\0)
      :for c :across "123.45"
      :if (char= c #\.) :collect c
        :else
          :collect (- (char-code c) z))
lovesan ★★☆
()
Ответ на: комментарий от lovesan

Классно!

а вот такое сможешь у себя провоерить у меня NIL выскакивает

(defvar teens-alist 
  '((0 . "") (10 . "десять") (11 . "одиннадцать") (12 . "двенадцать") 
    (13 . "тринадцать") (14 . "четырнадцать") (15 . "пятьнадцать") 
    (16 . "шестнадцать") (17 . "семнадцать") (18 . "восемнадцать") (19 . "девятнадцать")))


(defun get-num (alist n)
  (if (= n 0)
      (car alist)
    (get-num (cdr alist) (- n 1))))


(format t "~a тысяч" (cdr (assoc (+ (* (get-num '(1 2) 0) 10) (get-num '(1 2) 1)) teens-alist))) ;;=> NIL

должно быть «двенадцать тысяч»

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

такой же «правильный» как жопоскрипт

ну реально, в ту же сторону

ни макросов, ни метапрограммирования нормального, ни нормальных рантаймов

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

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

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

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

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

Лаконично это вот так:

{x - "0"*~x="."} "123.45"


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

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

Сразу видно, не работал в проде с бидоном.

«Лаконичность» там заключается только названиях встроенных функций, которые необходимо делать короткими только как раз в исключительно verbose и отвратительно малоэкспрессивных языках

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

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

Смотри, к примеру, примитивы в APL.

Да, и обычные арифметические операции в APL могут действовать поэлментно, в примере выше (который на K) по сути ничего кроме арифметики и не используется.

и почему в лиспе их нет

Ну я поискал сейчас и нашёл https://github.com/Lisp-Stat/array-operations. Но это выгляит как плохой клон numpy, который в свою очередь довольно таки плох.

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

PS: да, я ещё вспомнил, что есть https://github.com/phantomics/april

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

без дополнительных библиотек

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

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

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

monk ★★★★★
()

Усложним задачу: преобразовать строку в последовательность чисел, заменив цифры их значениями, а любые другие символы — их кодами ASCII.

(defn string-to-ints
  "Maps digits of string `s` to themselves and other characters to their ASCII codes."
  [s]
  (let [zero-code   (int \0)
        digit       (set (range 0 10))
        char-to-int (comp #(or (digit (- % zero-code)) %) int)]
    (map char-to-int s)))
(string-to-ints "-123.45e12")
;; => (45 1 2 3 46 4 5 101 1 2)

(string-to-ints "+123.45E-12")
;; => (43 1 2 3 46 4 5 69 45 1 2)
Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от Nervous

Ты из меня тут программиста не делай. И используй общий Лисп пожалуйста, а то я прочитать не могу.

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

В переводе на CL, это будет не вот это извращение с лямбдами, а вот так:\

Классно!

Классно, да. Главное, в macroexpand этой «не извращенной лямбдами» «красоты» не заглядывать. Любители колбасы не должны знать, из чего она производится. Любители пихать loop во все дыры не должны знать, во что он разврорачивается.

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

А какой смысл этого требования?

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

Точно так же, как тебе не нужна отдельная библиотека для возведения в степень или взятия корня числа.

В лиспе можешь переопределить себе + в своей программе во что хочешь.

Да, можносделать. Но я спрашивал есть ли базовые вещи из коробки.

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

открываешь интерпретатор, вводишь короткое выражение, решающее задачу, и сразу получаешь ответ

О чём там была речь, о поэлементном сложении векторов одним выражением?

Извольте.

(map + [1 2 3] [4 5 6])
;; => (5 7 9)
Nervous ★★★★★
()
Ответ на: комментарий от quantum-troll

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

Коротких выражений на все задачи не напасёшься. А возможность написать первой строкой (ql:quickload 'april) и получить весь APL или написать (ql:quickload "readable") (readable:enable-sweet) и использовать отступы вместо скобок намного полезнее.

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

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

Где X – абсолютно что угодно.

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

[chr if chr == '.' else ord(chr) - ord('0') for chr in "123.45"]

Давайте разберём это выражение по порядку

[

Начинается с открывающей скобки. Круто. Удобно. Но если хочется писать на лиспе, на лиспе и пишите.

chr

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

for chr in "123.45"

Ага, это переменная цикла. Прыгаем обратно в начало

if

Т.е то, что было слева — это then часть условного оператора

chr == '.'

Это просто, это условие.

else ord(chr) - ord('0')

А это оказывается else часть. Ну естественно и самоочевидно, что then if else читается проще, нежели if then else во всех вообще (включая Питон) остальных языках.

Сделано просто на пять с плюсом.

ugoday ★★★★★
()

P.S. Если не любишь цыклы, но любишь стрелочные макросы (а как их не любить-то?!).

* (->> "123.45"
     (map 'list #'char-code)
     (mapcar #'(lambda (c)
                 (if (= c 46) c
                     (- c 48)))))
(1 2 3 46 4 5)
ugoday ★★★★★
()
Ответ на: комментарий от ugoday

любишь стрелочные макросы (а как их не любить-то?!)

Мы любили всё на свете, кроме шила и гвоздя (тм).

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

Пффф...

[f x | x <- "123.45"]
       where f '.' = -1
             f  c  = ord c - ord '0'

— Haskell

[for c in "123.45" -> if c = '.' then -1 else int c - int '0']

— F#

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

Так это почти на любом языке можно написать такой ванлайнер.

Именно. И на любом языке это будет выглядеть лучше, и будет интуитивно понятнее, чем в Питоне :)

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

Что угодно на любом языке

будет выглядеть лучше, и будет интуитивно понятнее, чем в Питоне

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

Я говорю именно про набор функций, а не про то, как они обозначаются. Элементарные вещи вроде http://aplwiki.com/wiki/From, http://aplwiki.com/wiki/Index_Of или http://aplwiki.com/wiki/Replicate, которых часто нет в языках.
Функции, чтобы оперировать массивами целиком вместо того, чтобы долбиться в циклы каждый раз, когда надо что-то сделать.
Конечно, +\1 ¯1 0['()'⍳x] (см. https://www.jsoftware.com/papers/50/50_05.htm) намного приятнее читать чем (scan + (select (list 1 -1 0) (index-of '()' x))), но синтаксис это уже второстепенный вопрос.

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

нужно мапать на каждый чих

Для каждого типа данных свои функции — минимум магии, максимум прозрачности. Это база.

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

Nervous ★★★★★
()
Ответ на: комментарий от quantum-troll

Конечно, +\1 ¯1 0['()'⍳x]

Это больше на понты похоже. А зачем? Ерунда какая-то.

saufesma
() автор топика
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария