LINUX.ORG.RU

Синтаксис и LISP'ы

 , ,


0

1

Часто можно наткнуться на мнение, что у лиспа(ов) нет синтаксиса. Хотелось бы понять, что конкретно тут имеется в виду.

Во-первых, синтаксическая запись s-expr'ов так же является некоторым языком, со своими синтаксическими правилами и возможностью описания посредством грамматики.

Во-вторых, различные диалекты лиспа вводят специальные дополнительные синтаксические конструкции, вроде [ и ] в clojure или typed racket.

Имеется в виду, что этот синтаксис прост и фактически без особых изменений определяет AST?


Буквально это выражается в отсутствии жесткой привязки собствено объектов к их символьному представленю в тексте. Так круглые скобки это лишь общепринятая условность которой конкретный пркладник может и пренебречь и заменить на какие-нибудь диграфы. Пример утрированый :) В переносном смысле подразумевают отказ от нескобочного «сахара» в угоду простоты кодогенерации. Пишем программы которые пишут программы!

синтаксис прост и фактически без особых изменений определяет AST?

Ну даже банальные скобочные макросы делают крайне резкой границу между тем что пишет програмист и тем AST-ом который будет жевать компилятор. Хотя скобки казалось бы одинаковые.

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

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

То есть, лисп настолько суров, что может сделать вот так:


curlyBrackets := method(call evalArgs)
squareBrackets := method(call evalArgs)

write(
 {1,2,3}, "\n",  [1,2,3]
)

# ::: list(1, 2, 3)
# ::: list(1, 2, 3)
?

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

В переносном смысле подразумевают отказ от нескобочного «сахара» в угоду простоты кодогенерации. Пишем программы которые пишут программы!

То есть вот это:

(()''#(caaaadr((',(cdaar'',,',(caaadddddddr'(expr)))))))
проще да?

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

С момента определения синтаксиса []{} мы можем использовать его вместо list(). И это остается выражением языка, first-class, как и ф-ция. В Io все есть выражение. Это, по-сути, и означает отсутствие синтаксиса, если по хорошему то рассуждать. А в сраном лиспе ты спецформы никуда не денешь. Да и макросы — это не выражения. Так что это все пиар на пустом месте.

anonymous
()
Ответ на: комментарий от anonymous
> (module m racket
    (provide (rename-out [app #%app]))
    (define-syntax (app stx)
    (define parens (syntax-property stx 'paren-shape))
    (syntax-case stx ()
      [(_ args ...) (if (or (eq? parens #\[) (eq? parens #\{))
                        #'(list args ...)
                        #'(#%app args ...))])))
> (module m2 racket
    (require 'm)
    (displayln [1 2 3]))
> (require 'm2)
(1 2 3)
> 
anonymous
()
Ответ на: комментарий от anonymous

Это, по-сути, и означает отсутствие синтаксиса

Нет, это как раз означает обратное. Отсутствие синтаксиса = синтаксис выражается минимальным набором грамматических правил.

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

А что, разве у меня обернуто что-то куда-то? Я так понимаю, у тебя это работает только внутри module m2? Если это так, то это детсад.

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

мало синтаксиса — не означает отсутствие его. Отсутствием синтаксиса можно считать отсутствие спецформ.

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

Я так понимаю, у тебя это работает только внутри module m2?

Работает где сделано (require 'm) очевидно. Можно специфицировать поведение хоть для каждого модуля по-своему.

Если это так, то это детсад.

В чем детсад? Везде, где а захочу, оно будет работать, как я захочу. А что тебе еще надо?

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

Отсутствием синтаксиса можно считать отсутствие спецформ.

Спецформы - это семантика, а не синтаксис.

мало синтаксиса — не означает отсутствие его.

«Отсутствия синтаксиса» (формального) быть не может. Если у тебя есть текст, то есть синтаксис. По-этому под «нету синтаксиса» подразумевается «синтаксиса очень мало, самый минимум».

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

Получается, макросы в лиспе мало чем отличаются от «макросов» в JS


Macro={
 self: function(){/**/},
 value: function(){},
 cerate: function(){return Object.create(this)},
 re: /\/\*([\s\S]*)\*\//,
 expr: function(){with(this) {return (self+"").match(re)[1]}},
}

with(macro=Macro.create()){
 self=function(){
  /* console.log({1,2,3})
  */
 },
 value=Function(
      expr()
        .replace(/\{/, "[")
        .replace(/\}/, "]")
    )
}

macro.value()

// ::: [ 1, 2, 3 ]

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

Спецформы - это семантика, а не синтаксис.

разупорись

Если у тебя есть текст, то есть синтаксис

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

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

Везде, где а захочу, оно будет работать, как я захочу. А что тебе еще надо?

Подозреваю, что вот так не будет работать.


write(
 {{1,2,3}, [1,2,3]}, "\n",  [{1,2,3}, [1,2,3]]
)

# ::: list(list(1, 2, 3), list(1, 2, 3))
# ::: list(list(1, 2, 3), list(1, 2, 3))
Да и много где еще...

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

Получается, макросы в лиспе мало чем отличаются от «макросов» в JS

коненчо, отилчаются. В js нет компайлтайма и, следовательно, макросов.

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

Подозреваю, что вот так не будет работать.

Конечно же будет:

> (module m racket
    (provide (rename-out [app #%app]))
    (define-syntax (app stx)
    (define parens (syntax-property stx 'paren-shape))
    (syntax-case stx ()
      [(_ args ...) (if (or (eq? parens #\[) (eq? parens #\{))
                        #'(list args ...)
                        #'(#%app args ...))])))
> (require 'm)
> (display (~a {{1 2 3} [1 2 3]} #\newline [{1 2 3} [1 2 3]]))
((1 2 3) (1 2 3))
((1 2 3) (1 2 3))
> 
Я же сказал, что везде, это же робуст-интерпрайз солюшион, в отличии от игрушечного ио.

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

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

И еще переопределить запятую. можно же?

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

можно


curlyBrackets := method(
 call message arguments at(0) asString split()
)
squareBrackets := getSlot("curlyBrackets")

write({1 2 3}, [1 2 3])

# ::: list(1, 2, 3)list(1, 2, 3)

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

посмотри, посмотри, сынок


setSlot("", method(call evalArgs))

write((1,2,3))

# ::: list(1, 2, 3)
Жалко, что нам лисперы пока ничего внятного, кроме клоунады не показали. Лисп могуч своей клоунадой, оказывается, Вон оно как, михалыч, а мужики то и не знали.

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

Я не сомневался, что можно. Просто было интересно как.

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

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

Не понял, о чем ты. Один раз пишем один макрос, там, где хотим его использовать - импортируем (один раз).

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

Тему уже все забыли. Ну и х с ней, это ж ЛОР.

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

Жалко, что нам лисперы пока ничего внятного, кроме клоунады не показали.

Так ты ничего ещё не просил показать. Проси, чо.

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

Жалко, что нам лисперы пока ничего внятного, кроме клоунады не показали.

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

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

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

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

И где ты тут что переопределил?

Я переопределил ровно то, что просили

переопределение _круглых_ скобок.

должно быть list(list(1,2,3))

что должно быть? Это список включающий один список, все равно что лисповский (list (list 1 2 3)) так оно и есть по-дефолту

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

тогда почему ты переписал первоначальный вариант

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

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

Так написал же.

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

Если бы они не были переопределены, было бы так write(list(1,2,3))

У тебя так и есть. А должно быть write list(list(1,2,3))

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

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

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

нет, у меня write((1,2,3)), разуй глаза.

Ну да, убираем первые скобки получается write(list(1,2,3)) убираем вторые скобки получается write list(list(1,2,3))

А у тебя только одни перегружены.

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

Ты бред какой-то несешь

где бред? У тебя написано ((1,2,3)) если ты перегрузил скобки, должно получиться list(list(1,2,3)), а получилось list(1,2,3)

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

Я тебе повторяю, (1,2,3) значит с момента переопределения то же самое, что и list(1,2,3). Это тебе не лисп, там нет никаких костылей, никаких перезагрузок, перезаписей и прочего говна. (1,2,3) — это выражение языка, функция с аргументами. В терминах ООП — это сообщение.

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

(1,2,3) значит с момента переопределения то же самое, что и list(1,2,3).

Правильно. А ((1,2,3)) значит list(list(1,2,3)), соответственно write((1,2,3)) = write list(list(1,2,3)). А у тебя внешние скобки не перегружены.

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

Исходя из отсутствия ответа на этот простой вопрос заключаю, что это невозможно.

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

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

Исходя из отсутствия ответа на этот простой вопрос заключаю, что это невозможно.

Сделай так, хотя бы.

unless := method(
  if(call evalArgAt(0), call evalArgAt(2), call evalArgAt(1))
) # Это твой макрос, аргументы не вычисляются

function := method(
 args := call message arguments
 lst :=list(call evalArgAt(1)) append (args at(2)) append (args at(3))
 doMessage(performWithArgList(args at(0) code, lst))
) 

function(if, 1>2, 1 print, 2 print) # подаешь нативный if в качестве аргумента
function(unless, 1>2, 1 print, 2 print) # подаешь свой макрос в качестве аргумента.

# out:
# 21

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

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

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

anonymous
()
Ответ на: комментарий от anonymous
(define-syntax-rule (yoba args ...)
  (args ...))

(yoba if (> 1 2 ) (display 1) (display 2))
(yoba unless (> 1 2 ) (display 1))

че сказать-то хотел?

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

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

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