> 1 <

Автор Сообщение

qaqa

Members


Статус

18 сообщений

Где: Russia
Род занятий:
Возраст:

#6907   2013-02-04 11:09 GMT+3 часа(ов)      
Привет, всем!

Немного сумбурный и не очень принципиальный вопрос

На данный момент предпочтительно применять define для внутренних определений, потому как более читабельно чем let формы. Но на практике это частенько приводит к ситуациям:
(define x
(let ()
(define y ...)
(define z ...))
(expr-using-y-and-z))


На мой взгляд let () режет глаза. Есть форма block из racket/block. В исходнике есть такой комментарий:
(define-syntax (block stx)
;; Body can have mixed exprs and defns. Wrap expressions with
;; `(define-values () ... (values))' as needed, and add a (void)
;; at the end if needed.

И в документации про нее есть немного.

В приведенном выше примере (на мой взгляд) форма block была бы уместнее.
Насколько я понимаю (может ошибаюсь), сейчас block эквиватентно let (). По крайней мере макростеппер показал одно и тоже. Сделал поиск по исходникам Racket и не нашел случаев использования.
Я начал пользоваться вместо let (), но racket/block не входит в racket/base и постоянно ее подключать немного напрягает.

Как считаете: был бы смысл в добавлении такой формы в base часть Racket? Кто нибудь еще пользуется?

qaqa

Members


Статус

18 сообщений

Где: Russia
Род занятий:
Возраст:

#6913   2013-02-08 21:37 GMT+3 часа(ов)      
Друг дай закурить , а в ответ тишина...

Есть тут кто живой?

misha

Moderators


Статус

1273 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#6914   2013-02-08 22:38 GMT+3 часа(ов)      
Цитата
На данный момент предпочтительно применять define для внутренних определений, потому как более читабельно чем let формы.
Ну, это с непривычки. У меня, например, появляется чувство дискомфорта, когда определения перемешаны с кодом. Правда если необходимо определить несколько больших локальных функций, то лучше использовать local.
Цитата
Насколько я понимаю (может ошибаюсь), сейчас block эквиватентно let (). По крайней мере макростеппер показал одно и тоже.
Ошибаетесь. Нужно смотреть исходники А что собственно должен был показать макростеппер?
Цитата
Как считаете: был бы смысл в добавлении такой формы в base часть Racket?
Лично я в этом не вижу смысла. Тем более в base.
Цитата
Кто нибудь еще пользуется?
Ну, если он вам так нравится, то возможно вам стоит создать свой собственный диалект.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#6915   2013-02-08 22:49 GMT+3 часа(ов)      
define предпочтительно перед let только внутри internal definitions contex. в выражении (define id ...) на месте многоточия - expression context. так что пиши обычный let ([...] ...) вместо (let () (define ...) ...)

qaqa

Members


Статус

18 сообщений

Где: Russia
Род занятий:
Возраст:

#6916   2013-02-09 10:53 GMT+3 часа(ов)      
Цитата
misha :
Ошибаетесь. Нужно смотреть исходники А что собственно должен был показать макростеппер?

Действительно ошибся. Вот примеры: пример1, пример2. В обоих примерах варианты 1 и 3 раскрываются в одно и тоже. А вариант 2 содержит еще один let-values.

отредактировал(а) qaqa: 2013-02-09 11:07 GMT+3 часа(ов)

qaqa

Members


Статус

18 сообщений

Где: Russia
Род занятий:
Возраст:

#6917   2013-02-09 11:02 GMT+3 часа(ов)      
Цитата
Kergan :
define предпочтительно перед let только внутри internal definitions contex. в выражении (define id ...) на месте многоточия - expression context. так что пиши обычный let ([...] ...) вместо (let () (define ...) ...)


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

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#6919   2013-02-09 20:11 GMT+3 часа(ов)      
Какие грабли?

qaqa

Members


Статус

18 сообщений

Где: Russia
Род занятий:
Возраст:

#6920   2013-02-09 22:22 GMT+3 часа(ов)      
Цитата

Kergan :
Какие грабли?


Цитата

Kergan :
так что пиши обычный let ([...] ...) вместо (let () (define ...) ...)

Я был не прав, и let () не эквивалентно block на 100%. Но вот есть конструкция block. Есть ли какие то подводные камни, если пользоваться (block (define ...) ...), а не let ([...] ...)?

rv82

Members


Статус

46 сообщений
http://rv82.ya.ru
Где: Russia
Род занятий:
Возраст:

#6921   2013-02-11 23:32 GMT+3 часа(ов)      
А почему бы не использовать let? Это только поначалу кажется, что код с let'ами нечитабелен. После небольшой практики это будет казаться естественным. Кстати, лично я не пихаю define внутрь других defin'ов. Другими словами, внутри функции лучше использовать именно let и ничего другого (не считая lambda, конечно же). Для некоторых реализаций scheme это не просто предпочтение, а требование.

С другой стороны, если Вам нравится использовать block, что Вам мешает это делать? Особенно, если Вы не собираетесь переносить свои программы на другие реализации scheme. Хотя и это не проблема. Данная конструкция легко реализуется с помощью макросов на любом scheme.

отредактировал(а) rv82: 2013-02-11 23:39 GMT+3 часа(ов)

qaqa

Members


Статус

18 сообщений

Где: Russia
Род занятий:
Возраст:

#6922   2013-02-12 09:40 GMT+3 часа(ов)      
Цитата
А почему бы не использовать let? Это только поначалу кажется, что код с let'ами нечитабелен. После небольшой практики это будет казаться естественным.

Я не говорил, что код c let нечитабелен, я имел в виду, что с define читабельнее (но это субъективно).
В плане кодирования (опять же субъективно) let менее удобен.
Вот приведу небольшой пример, как я обычно пишу на Racket. Вот появилась какая то задачка, или просто идейку проверить захотелось - открываю DrRacket и пишу код в виде последовательных define в топе модуля. Ясно дело, что больше половины случаев define не нужны в топе, и их бы лучше в виде let* оформить сразу. Но вот может я так пишу коряво, не продумываю сразу структуру, с let я в любом случае вожусь чуть дольше чем стоило бы. Ну и я подумал на досуге, раз style guide нынче советует define для внутренних определений, то может есть способ не используя замену define на let отрефакторить такой говнокод? В коде самого Racket, видел что-то наподобие:
(define-values (a b ...)
(let ()
(define (f x)
......)
(values (f 1)
(f 2)
...)))

Спрятав промежуточные define под let() получаем то, что требовалось. Но (опять же субъективно) режет глаза let в таком виде. И вот случайно наткнулся на racket/block и стал пользоваться им вместо let(). Захотелось обсудить - кто как к такому подходу относится. Раз Racket на совместимость с другими схемами уже забил, почему бы дальше не пойти Какие минусы от такого подхода?

Ну и у block судя по документации:
Цитата
(block defn-or-expr ...)
Supports a mixture of expressions and mutually recursive definitions, as in a module body. Unlike an internal-definition context, the last defn-or-expr need not be an expression.

Цитата
internal-definition context : in a nested context that allows both definitions and expressions.

Цитата
Different core syntactic forms parse sub-forms using different contexts. For example, a let form always parses the right-hand expressions of a binding in an expression context, but it starts parsing the body in an internal-definition context.

есть особенность:
Цитата
the last defn-or-expr need not be an expression


Я не сильно глубоко все это знаю, может от такого подхода есть минусы серьезные? Возможно я вообще что-то неправильно делаю?

отредактировал(а) qaqa: 2013-02-12 11:30 GMT+3 часа(ов)

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#6923   2013-02-13 14:26 GMT+3 часа(ов)      
Цитата
Ясно дело, что больше половины случаев define не нужны в топе, и их бы лучше в виде let* оформить сразу.

А они и не в топе, они в module level. По-этом нету никакого такого особенного смысла засовывать их еще в дополнительный let*.

Цитата
Unlike an internal-definition context, the last defn-or-expr need not be an expression.

Вот по-этому block, видимо, и не стоит применять.

qaqa

Members


Статус

18 сообщений

Где: Russia
Род занятий:
Возраст:

#6924   2013-02-13 16:25 GMT+3 часа(ов)      
Цитата
А они и не в топе, они в module level.

Спасибо за поправку. Лучше мне такими терминами, без более глубокого вникания, не оперировать .
Цитата
По-этом нету никакого такого особенного смысла засовывать их еще в дополнительный let*.

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

Вместо:
(define x1 ...)
(define y1 ...)
(define z1 (do-something1 x1 y1))
(define x2 ...)
(define y2 ...)
(define z2 (do-something2 x2 y2))

Получается:
(define z1
(let ([x ...]
[y ...])
(do-something1 x y)))
(define z2
(let ([x ...]
[y ...])
(do-something2 x y)))
 

Или:
(define z1
(block
(define x ...)
(define y ...)
(do-something1 x y)))
(define z2
(block
(define x ...)
(define y ...)
(do-something2 x y)))


Цитата
Kergan :
define предпочтительно перед let только внутри internal definitions contex. в выражении (define id ...) на месте многоточия - expression context. так что пиши обычный let ([...] ...) вместо (let () (define ...) ...)

Меня только вот это ваше высказывание смущает

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#6925   2013-02-14 14:29 GMT+3 часа(ов)      
Цитата
Есть смысл для повторного использования имен в промежуточных вычислениях.

а первый вариант чем не устраивает?

посмотрел block - он реализован через явный local-expand с добавлением идентификаторов в контекст "руками". Я лично не сильно доверяю таким макросам.

qaqa

Members


Статус

18 сообщений

Где: Russia
Род занятий:
Возраст:

#6926   2013-02-15 09:38 GMT+3 часа(ов)      
Цитата
а первый вариант чем не устраивает?

Не понятно - какой из ни первый. Меня бы устроил последний вариант, на месте block может быть любая адекватная форма. Можно и let() но режет глаз, на мой взгляд.

Цитата
посмотрел block - он реализован через явный local-expand с добавлением идентификаторов в контекст "руками". Я лично не сильно доверяю таким макросам.

В моем случае оно работает - это все мои аргументы

По большому счету, мне не особо важно как это будет называться, и как это будет реализовано. Сейчас в racket нет идиоматичной конструкции для таких случаев, кроме (let ([id expr] ...)). В How to Program Racket во всех примерах let-офобия, а по этому случаю ничего не сказано.

qaqa

Members


Статус

18 сообщений

Где: Russia
Род занятий:
Возраст:

#6944   2013-03-11 10:17 GMT+3 часа(ов)      
Наткнулся в http://racket-lang.org/irc-logs/20120318.txt:

16:52 chandler: I'm a little confused as to why (local (define y 1) y) doesn't work, actually.
16:53 chandler: Er, in a top-level context that is.
17:13 jeapostrophe: chandler: you are missing a paren
17:14 jeapostrophe: rudybot: (local [(define y 1)] y)
17:14 rudybot: jeapostrophe: your sandbox is ready
17:14 rudybot: jeapostrophe: ; Value: 1
17:14 chandler: Oh!
17:14 chandler: Sorry. I must not be able to read today.
17:19 chandler: Oh, it's `block' I was trying to think of, not `local'.
17:20 chandler: Though apparently `block' can't be used in an expression context...
17:21 jeapostrophe: chandler: ya, that's different/nicer, but actually unnecessary because 'begin' already does that now
17:22 chandler: Is there a form equivalent to (let () body ...) to let internal definitions be used in an expression context? It's obviously semantically unnecessary, but it's nice to not have an empty binding form where it's not needed.
17:27 jeapostrophe: chandler: begin does that
17:27 chandler: rudybot: eval (define x (begin (define y 1) y))
17:27 rudybot: chandler: your sandbox is ready
17:27 rudybot: chandler: error: #<undefined>:1:17: define: not allowed in an expression context in: (define y 1)
17:28 chandler: What am I missing?
17:29 jeapostrophe: rudybot: (version)
17:29 rudybot: jeapostrophe: ; Value: "5.2.1"
17:31 jeapostrophe: chandler: hmm, i guess the splicing behavior of begin causes a problem. block works there though
17:31 chandler: rudybot: eval (define x (block (define y 1) y))
17:31 rudybot: chandler: error: #<undefined>:1:17: define: not allowed in an expression context in: (define y 1)
17:33 jeapostrophe: rudybot: (require racket/block) (define x (block (define y 1) y))
17:33 rudybot: jeapostrophe: hmm. i guess it depends on the kind of people that you're trying to ensure understand your code. i might be wrong, but i'd think any seasoned lisp programmer would automatically translate car, cdr to what those functions represent (i.e., first and rest). i agree it's a stumbling block for new programmers (since they have to understand new notation) and that the fewer such requirements are made for people to mem
17:33 jeapostrophe: rudybot: (define x (block (define y 1) y))
17:33 rudybot: jeapostrophe: error: #<undefined>:1:17: define: not allowed in an expression context in: (define y 1)
17:34 chandler: jeapostrophe: Nevermind rudyboy; I see now.
17:34 jeapostrophe: doesn't work because it is parsed as (#%app block (define y 1) y)
17:34 chandler: "rudybot"
17:34 chandler: Yes, I figured that out.
17:34 jeapostrophe: because block isn't in racket or racket/base, but racket/block
> 1 <


Онлайн :

0 пользователь(ей), 32 гость(ей) :




Реклама на сайте: