Scala

Nov. 6th, 2012 04:15 am
metaclass: (Default)
[personal profile] metaclass
Читаю книжку Одерского, до основной шизы еще не добрался, но такое ощущение, что в скале чрезмерно много синтаксического сахара. Типа "тут вы можете скобки опустить, а тут вместо скобок использовать фигурные скобки, а тут мы прямо в параметрах класса сделаем их полями, а в multiline string literal вы можете сделать отступ и stripMargin" и прочая и прочая в том же духе.
Основное из этого, видимо - function literals и вызов методов в стиле a methodName b, без точек и скобок, что делает код более лаконичным, одновременно позволяя при желании превратить код в нечитабельный ад.

Заодно по наводке [livejournal.com profile] jdevelop глянул на http://spray.io/ https://github.com/spray/spray/wiki
Примеры там, конечно, знатный abuse возможностей языка и вычислений на типах, типа extraction-директив с HList в качестве параметра типа.

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

PS: Вот, к примеру:
https://github.com/spray/spray/blob/master/docs/documentation/spray-routing/code/docs/HttpServiceExamplesSpec.scala

В SimpleService HttpResponse реализован как html-код написанный прямо внутри скала-кода. Сижу уже 30 минут ищу, где это преобразование реализовано и как. Т.е. не видя отдельных литералов и их типов (которые без загрузки всего оного кода с зависимостями в IDE/интерпретатор еще и не увидишь), с ходу догадаться, что происходит, достаточно сложно. XML literals, встроенные в язык и где-то implicit для конверсии.

PPS: implicit evidence:
http://jim-mcbeath.blogspot.com/2008/11/scala-type-infix-operators.html
http://stackoverflow.com/questions/3427345/what-do-and-mean-in-scala-2-8-and-where-are-they-documented

По-моему, это уже достаточно сложно, чтобы увлечь психов и стать новыми крестиками. Вот [livejournal.com profile] xeno_by еще приделает макросы - и совсем хорошо станет.

Date: 2012-11-09 04:20 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
> Если вы не знали, то вот вам пример (я уж задолбался его приводить):

Такой if в любом языке пишется, достаточно будет обернуть аргументы в delay. С другой стороны, в хаскеле нельзя реализовать свой begin - он в хаскеле встроен (и называется case). То есть в хаскеле приходится руками оборачивать выражения в force. Это известная эквивалентность ленивого и энергичного порядка. На языке теорката она выражается в том, что в категории соответствующей ленивому порядку нету сумм, а в категории, соответствующей энергичному порядку - произведений, т.о. полученные категории дуальны.

Date: 2012-11-09 09:25 am (UTC)
From: [identity profile] thesz.livejournal.com
В принципе, вы подтвердили мою мысль, но не до конца. Важно количество обёрток.

В строгом языке - все аргументы, в ленивом - в нескольких местах.

Date: 2012-11-10 09:37 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
В ленивом языке тоже все аргументы приходится оборачивать. Я же говорю - категории дуальны. То есть соответствие между теми местами, где оборачиваем в лени, взаимооднозначно с теми, где оборачиваем в энергичном языке. Против математики не попрешь :)

Date: 2012-11-10 10:45 am (UTC)
From: [identity profile] thesz.livejournal.com
Вы забываете про видимое программисту. В ленивом языке программисту необходимо изменить меньшее количество мест для создания энергичного кода.

Date: 2012-11-11 12:57 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
Я же говорю - мест столько же.
В ленивом языке надо всегда ставить force вокруг первого аргумента кейза, В энергичном - delay вокруг веток if. Но поскольку и там и там это делает невыразимая в рамках языка спецформа (case и if соответственно)., то на практике ни там ни там никто вообще ничего не ставит. Важно, что ситуация совершенно зеркальна.

Тут следует только отметить, что force в ленивом ЯП выразить нельзя (если у нас уже не встроен кейз, который неявно вызывает force как в хаскеле), А вот delay выразить можно - это санка. Естественно, если мы говорим о классическом лямбда-исчислении, то там будет нарушена семантика (т.к. санка необходимо должна иметь переменную), так что указанная выше дуальность не нарушена. Но с точки зрения "человеческой" семантики функция без аргументов, которая моделирует delay в энергичном языке выглядит намного естественнее и лучше вписывается в исчисление, чем force, который вообще неясно как выражать, чистый хак.

Date: 2012-11-11 01:23 am (UTC)
From: [identity profile] thesz.livejournal.com
Вот числа Фибоначчи:

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

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

http://thesz.livejournal.com/906786.html

fibsAsBottom = strictTail $ strictHead $ fibs

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

Date: 2012-11-11 03:10 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
> Сколько и чего вам нужно будет написать, чтобы сделать из бесконечного энергичного списка чисел Фибоначчи ленивый?

Я не понял вопроса. Что из чего следует сделать? Известно, что "энергичные бесконечные списки" не существуют. Как из того, что не существует, можно сделать нечто существующее?

Сформулируйте четко и ясно, что вы хотели сказать, пользуясь общепринятой терминологией и не выдумывая своих понятий. Это необходимое условие, чтобы собеседник мог вас понимать.

Напоминаю, о чем мы говорили - на каждый if/case в энергичном/ленивом языке надо ставить delay/force, иначе ничего не будет работать. Т.о. места обязательных расстановок lazy/strict аннотаций строго совпадают. При чем эти аннотации расставляются автоматически, соответствующей спец-формой (if/case). В результате в коде никаких аннотаций нет. Ни в ленивом ни в энергичном случае. Это подтверждается экспериментально - мы спокойно пишем код безо всяких аннотаций. Потому в большинстве языков даже и возможности расставить аннотации руками нет - это просто никому не нужно.

Теперь, еще раз, что вы хотите доказать и как это соотносится с числами Фибоначчи?

Date: 2012-11-11 10:04 am (UTC)
From: [identity profile] thesz.livejournal.com
Я подожду, пока вы поймете. Мне не сложно. Вы можете позволить себе не торопиться и как следует все обдумать.

Date: 2012-11-11 03:31 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
Собственно, прочитав по ссылке:
> По моим соображениям, при энергичном порядке вычислений по умолчанию и ленивости в виде аннотаций, эти самые аннотации надо расставлять везде, где по дизайну программы могут проходить ленивые значения и их надо сохранить ленивыми. Это практически все библиотечные функции, по-моему. А также очень много мест в коде программы - еще раз подчеркну: везде, где по дизайну программы могут проходить ленивые значения и их надо сохранить ленивыми.

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

Ваш аргумент можно было бы принять, но вы подразумеваете тут полную бесконтрольность - то есть у нас-де ВНЕЗАПНО может куда-нибудь прийти санка, а раз может...
Но такой ситуации быть не должно, конечно же - все места, куда должно прийти ленивое вычисление, должны быть фиксированы заданием соответствующего типа. f: Promise Int -> Int - может прийти санка, f : Int -> Int - не может прийти санки. Делаем Promise монадой и обеспечиваем автоматический лифтинг ф-й в нее - в результате весь код будет выглядеть одинаково - и ленивый и энергичный, а нам лишь надо будет в граничных местах заворачивать или вытаскивать значение из lazy-монады где это явно надо.

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

Date: 2012-11-11 10:18 am (UTC)
From: [identity profile] thesz.livejournal.com
Ага, вы поняли.

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

Date: 2012-11-12 05:47 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
То, что в лени задумываться не надо - это какой-то сомнительный тезис, вспомним хотя бы проблемы с оптимизацией и оценкой сложности ленивых программ.
В общем, описанное выше решение (фиксация порядка вычислений типами) как раз и нужна за тем, чтобы не задумываться - то есть если нам хочется узнать, что и как вычисляется, то нам в этом случае не надо исследовать control-flow, достаточно посмотреть на тип выражения.
Еще можно вспомнить о том, что бОльшая часть юзкейзов лени покрывается ленивыми структурами. В этом смысле какой-нибудь map для списка не должен писаться руками - он должен быть сгенерирован автоматически, исходя из определения АТД "List" и генерализованного определения map для произвольного АТД (как, например, это можно делать в Clean). Для ленивого списка мы автоматически получим ленивый map, для энергичного списка - энергичный map, а переход между способами вычисления будет выглядеть как явное преобразование типа соответствующей структуры.

Date: 2012-11-12 06:27 am (UTC)
From: [identity profile] thesz.livejournal.com
Проблемы с оптимизацией начинаются уже после написания программы. Если начинаются вообще.

Date: 2012-11-12 08:55 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
Проблемы с оптимизацией я упомянул лишь для демонстрации того, что не так все очевидно с control-flow ленивой программы. Если бы было очевидно - не было бы проблем с оптимизацией и оценкой сложности.

Date: 2012-11-12 09:00 am (UTC)
From: [identity profile] thesz.livejournal.com
Как бы это сказать помягче.

Проблем с оптимизацией ленивой программы не более, чем проблем с оптимизацией программы на C под Cell BE. Со сложностью то же самое.

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

Date: 2012-11-12 11:46 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
Вы полностью пропустили то, что я написал :)

Начнем сызнова - ваш тезис, как я понимаю, состоит в следующем: ленивый порядок экономит время программиста, поскольку делать выводы о ходе вычисления проще при ленивом порядке.

Здесь есть посылка (делать вывод о ходе вычисления проще при ленивом порядке) и следствие (программист экономит время).

Чтобы следствие получилось верным, надо показать, что верна посылка. Но тут-то и возникает проблема - есть известные факты, которые посылку опровергают. То есть программист, может, время и экономит - но явно не потому, что в ленивом порядке делать выводы о ходе программы проще - т.к. известно, что делать эти выводы при ленивом порядке _сложнее_.

Date: 2012-11-12 07:25 pm (UTC)
From: [identity profile] thesz.livejournal.com
>То есть программист, может, время и экономит - но явно не потому, что в ленивом порядке делать выводы о ходе программы проще - т.к. известно, что делать эти выводы при ленивом порядке _сложнее_.

Вот тут дилемма.

Стоит ли нашему читателю верить Валентину Будаеву или Джону Хьюджесу и Леннарту Аугустссону?

Вадлер, кстати, утверждает дуальность call-by-name и call-by-value. Поэтому на статью с показанной дуальностью call-by-value и call-by-need я бы хотел посмотреть.

И ещё хочу попросить у вас ссылку на статью, которая показывает повышение модульности программ на энергичном языке по сравнению с ленивым. WhyFP Джона Хьюджеса показывает повышение модульности программ только для ленивых языков, надо исправить это упущение.

Date: 2012-11-13 02:23 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
> Стоит ли нашему читателю верить Валентину Будаеву или Джону Хьюджесу и Леннарту Аугустссону?

А зачем кому-то верить? Я предпочитаю смотреть на экспериментальные факты, а не на чьи-то мнения и статьи (которые тоже суть не более чем мнения). А экспериментальные факты таковы, что при оценке сложности и оптимизации программ ленивый порядок не упрощает, а усложняет reasoning.

> И ещё хочу попросить у вас ссылку на статью, которая показывает повышение модульности программ на энергичном языке по сравнению с ленивым. WhyFP Джона Хьюджеса показывает повышение модульности программ только для ленивых языков, надо исправить это упущение.

Во-первых, это статья о том, как FP поднимает модульность в языках вроде хаскеля. К другим ЯП сделанные в статье выводы, конечно же, неприменимы. Во-вторых, статья рекламная - а энергичному порядку реклама не требуется, Это лень на данный момент маргинальна.В-третьих, я могу ошибаться (вы меня тогда поправьте), но вот тот же Саймон Пейтон-Джонс как-то высказывался на тему того, что лучше было бы хаскелю быть энергичным, нет?

> Поэтому на статью с показанной дуальностью call-by-value и call-by-need я бы хотел посмотреть.

call-by-need и call-by-name изоморфны в обсуждаемом смысле.

Date: 2012-11-13 04:19 am (UTC)
From: [identity profile] migmit.livejournal.com
> А экспериментальные факты таковы, что при оценке сложности и оптимизации программ ленивый порядок не упрощает, а усложняет reasoning.

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

Если же использовать семантику Скотта, то рассуждения становятся проще в разы (а то и в десятки раз).

Date: 2012-11-14 03:46 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
> Неверно.

От того, что вы белое назовете черным, оно не станет таковым. Проблемы с оценкой сложности ленивых программ - известный факт.

> Если же использовать семантику Скотта, то рассуждения становятся проще в разы (а то и в десятки раз).

Было бы неплохо продемонстрировать этот тезис на каком-нибудь простом примере. Ну, например, докажите в семантике Скотта ассоциативность ф-и append.

Date: 2012-11-14 08:21 am (UTC)
From: [identity profile] migmit.livejournal.com
> Проблемы с оценкой сложности ленивых программ - известный факт.

Фу, как некрасиво. Только что говорили вообще про рассуждения о программе — и вдруг спрыгиваете на оценку сложности.

> Ну, например, докажите в семантике Скотта ассоциативность ф-и append.

Это которая в Хаскеле (++)? Конкатенация списков?

Пожалуйста.

Определение:

append [] ys = ys
append (x:xs) ys = x : append xs ys

Требуется доказать:

append xs (append ys zs) = append (append xs ys) zs

Расшифровка определения: если положить

t f [] ys = ys
t f (x:xs) ys = x : f xs ys

то append — наименьшая неподвижная точка функции t, то есть, наименьшая f, для которой t f = f.

Далее, если f такова, что f xs (append ys zs) = append (f xs ys) zs, то t f тоже удовлетворяет этому условию, так как

t f [] (append ys zs) = append ys zs = append (t f xs yz) zs
t f (x:xs) (append ys zs) = x : f xs (append ys zs) = x : append (f xs ys) zs = append (x : f xs ys) zs = append (t f (x:xs) ys) zs

Функция (_|_) этому условию удовлетворяет:

(_|_) xs (append ys zs) = (_|_) = append (_|_) zs = append ((_|_) xs ys) zs

Значит, условие удовлетворяется для tn(_|_) при любом натуральном n. В силу непрерывности обеих его частей по f, оно удовлетворяется также и для supntn(_|_) — а это и есть append.
Edited Date: 2012-11-14 08:21 am (UTC)

(no subject)

From: (Anonymous) - Date: 2012-11-15 04:46 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.livejournal.com - Date: 2012-11-15 10:21 am (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-15 12:21 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.livejournal.com - Date: 2012-11-15 08:44 pm (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-16 02:12 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.livejournal.com - Date: 2012-11-16 08:31 am (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-16 09:54 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.livejournal.com - Date: 2012-11-16 11:00 am (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-16 11:36 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.livejournal.com - Date: 2012-11-16 01:08 pm (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-16 01:45 pm (UTC) - Expand

(no subject)

From: [identity profile] migmit.livejournal.com - Date: 2012-11-16 05:47 pm (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-17 03:41 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.livejournal.com - Date: 2012-11-17 04:05 am (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-17 07:18 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.livejournal.com - Date: 2012-11-17 06:01 pm (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-18 04:03 am (UTC) - Expand

(no subject)

From: [identity profile] migmit.livejournal.com - Date: 2012-11-18 11:11 am (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-25 12:53 pm (UTC) - Expand

Date: 2012-11-13 10:20 am (UTC)
From: [identity profile] thesz.livejournal.com
Ага, я рад признанию неприменимости подходов Хаскеля в других ЯП.

Действительно, СПЖ сказал в интервью, что чистота важнее порядка выполнения и что "следующий Хаскель" может быть и энергичным. Просто проще всего сделать язык чистым с помощью ленивого порядка выполнения.

Который, к тому же, ещё и удобней для программирования.

Насчёт маргинальности... По-моему, умного человека смущает не количество единомышленников, а их качество. Мне нравится Haskell community.

Прошу прощения, но упомянутые вами "эксперименты" пока выглядят всего лишь как ещё одно мнение. Эксперименты должны иметь результаты в виде цифр. Вот таковые про Хаскель и энергичные языки.

И я хочу увидеть чьё-то ещё мнение насчёт изоморфизма call-by-value и call-by-need. Только вашего мне недостаточно. Вы рассматриваете этот пока ещё не существующий для меня дуализм на слишком низком уровне.

Date: 2012-11-14 03:49 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
Вы опять не читаете, что я пишу. Надоело.

> Вот таковые про Хаскель и энергичные языки.

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

(no subject)

From: [identity profile] thesz.livejournal.com - Date: 2012-11-14 08:29 am (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-15 04:54 am (UTC) - Expand

(no subject)

From: [identity profile] thesz.livejournal.com - Date: 2012-11-15 08:53 am (UTC) - Expand

(no subject)

From: [identity profile] berezovsky.livejournal.com - Date: 2012-11-15 09:16 am (UTC) - Expand

(no subject)

From: [identity profile] thesz.livejournal.com - Date: 2012-11-15 10:54 am (UTC) - Expand

(no subject)

From: [identity profile] valentin budaev - Date: 2012-11-15 12:01 pm (UTC) - Expand

Date: 2012-11-11 03:38 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
> Модифицировать map мне не надо, а значит, выше модульность.

Фактически, вы сделали следующее:
map = tmp
теперь если я хочу сделать map энергичным, то просто переопределяю tmp, а реализацию map менять не надо!

Ну так это работает и с энергичным и с ленивым порядком :)

Date: 2012-11-11 01:29 am (UTC)
From: [identity profile] thesz.livejournal.com
Вдогонку.

Ленивое ЛИ Тьринг полно. Значит, в нем можно реализовать force.

В приведенных мной примерах это и делается.

Date: 2012-11-11 03:01 am (UTC)
From: [identity profile] valentin budaev (from livejournal.com)
> Ленивое ЛИ Тьринг полно.

Энергичное тоже :)

> Значит, в нем можно реализовать force.

Нет, нельзя. условно говоря, delay/force нельзя реализовать в энергичном/ленивом ЯП. С тьюринг-полнотой это не связано - тьюринг-полнота о вычислимости, а не о выразительности.

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

Profile

metaclass: (Default)
metaclass

April 2017

S M T W T F S
      1
2345678
9101112 131415
16171819202122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 3rd, 2025 08:24 pm
Powered by Dreamwidth Studios