[personal profile] sassa_nf
2.2.0 :010 > f 1, 2 { |x| x+1 }
SyntaxError: (irb):10: syntax error, unexpected '{', expecting end-of-input
2.2.0 :011 > f (1, 2) { |x| x+1 }
SyntaxError: (irb):11: syntax error, unexpected ',', expecting ')'
2.2.0 :012 > f(1, 2) { |x| x+1 }
 => 2

what's their problem?!

Date: 2016-07-16 02:44 pm (UTC)
From: [identity profile] juan-gandhi.livejournal.com
Японцы... Мац, он обращает внимание на мелкие буковки, а большая картина ему не видна.

Date: 2016-07-17 10:43 am (UTC)
From: [identity profile] vinslivins.livejournal.com
это всё потому, что бедному руби нужно угадывать, метод это или переменная (он их намеренно путает.)
irb(main):008:0> def f a,b; end
=> nil
irb(main):009:0> f 1, 2 do |x| x+1 end
=> nil

Date: 2016-07-17 11:23 am (UTC)
From: [identity profile] sassa-nf.livejournal.com
нет, жалуется же что это синтаксическая ошибка!

Вопрос на самом деле в том, "(" - это токен или нет. Если токен отдельный от var name, то это первый язык, в котором нельзя между токенами произвольно _вставлять_ пробелы.

Date: 2016-07-17 12:58 pm (UTC)
From: [identity profile] vinslivins.livejournal.com
я не знаю точной терминологии, но по-моему почти все языки программирования парсятся в бытовом смысле неоднозначно. иногда можно вставлять пробелы, иногда нельзя. в джаваскрипте был пример, когда две отдельных программы компилируются, а если их сделать одна под другой, то нет, несмотря на символ новой строки.

Date: 2016-07-24 10:23 pm (UTC)
From: [identity profile] salas.livejournal.com
В js, кажется, грабли этого вида ровно одни, и всё-таки не на лексическом уровне: это магическая инструкция "use strict", которая меняет смысл остального кода, когда является первой в файле (или теле функции).

Date: 2016-07-25 08:32 pm (UTC)
From: [identity profile] vinslivins.livejournal.com
http://nponeccop.livejournal.com/311583.html

Date: 2016-07-17 04:39 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
Этот пример, кстати, демонстрирует какую-то другую проблему. Например, что есть лямбды, проки и блоки, и у всех из них свои нюансы взаимодействия с функциями.

Date: 2016-07-17 07:00 pm (UTC)
From: [identity profile] vinslivins.livejournal.com
в руби (особенно, если смотреть именно как на платформу, т.е. на рельсы и гемы) это - наименьшая проблема :)

в руби всегда был синтаксический диабет, но это с лихвой перекрывается литературным программированием рельсов, если смотреть глазами пуриста джавы, например.
(в качестве примера скажу, что "класс программы" ("модели данных") в рельсах имеет 740 публичных методов и 30 приватных)

Date: 2016-07-17 09:08 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
Да из-за синтаксического диабета еще проблемы с написанием тестов. Чтобы понять, что нужно мокать, нужно глубоко понимать, кто что вызывает - а из-за фокусов это не всегда можно узнать просто глядя на программу.

Date: 2016-07-18 01:35 am (UTC)
From: [identity profile] vinslivins.livejournal.com
гм. да не, после недлинного изучения руби (главное, чтобы было кого спросить), всегда понятно, кто кого вызывает, и как мокать.
есть пример, где непонятно?

Date: 2016-07-18 07:08 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
спасибо за комментарии. Нет, не то, чтобы нельзя разобраться, что к чему; не очень ясно, какие проблемы возникли, что они были решены таким-то способом.

Ок, я могу понять что-то типа горизонтальной композиции кода (навроде частного одностороннего случая pipes), но как-то не очень понятно, как бы оно выражалось в общем случае?

2.2.0 :004 > f {|x| yield (x+1)} {|y| yield y*2} {|z| z}
SyntaxError: (irb):4: syntax error, unexpected { arg, expecting end-of-input

Date: 2016-07-25 08:39 pm (UTC)
From: [identity profile] vinslivins.livejournal.com
[1,2,3].
map {|e| e + 1}.
map {|e| e*2}.
reduce {|e, a| e + a }

я всё хотел накопать сюда хороших и разных рабочих примеров реальных задач, но не найду время. но, в общем, так можно и олимпиадные задачи мап-мап-мап-редьюс, так и файлы-отчёты-бог знает что ещё таскать, готовить и выполнять. мап, флатмап и редьюс (в основном сложение, ага) рулят)
Edited Date: 2016-07-25 08:41 pm (UTC)

Date: 2016-07-25 09:29 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
ну это-то понятно. Но чем оно отличается от передачи функции?

Date: 2016-07-26 08:32 pm (UTC)
From: [identity profile] vinslivins.livejournal.com
передача блока кода = передача замыкания (= функции).
(т.е. ничем.)
Edited Date: 2016-07-26 08:33 pm (UTC)

Date: 2016-07-17 07:02 pm (UTC)
From: [identity profile] vinslivins.livejournal.com
что любопытно, это совершенно не мешает работать - я встречал только одну конструкцию, где это всё плохо компилируется:

Mapping = {
a: begin
вот где-то здесь со скобками расползается нормальная компиляция
end,
}


А так, за все три года в синтаксис упирался только два раза, и всё.

Date: 2016-07-17 09:05 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
а че вообще рельсы на руби писано? Что-то такое особое в руби или звезды сошлись?

Date: 2016-07-18 01:46 am (UTC)
From: [identity profile] vinslivins.livejournal.com
руби из всех известных мне языков ближе всего к литературному программированию.

там есть if, а есть unless - чтобы лучше читалось.
есть даже Object#nil? , если это поможет вот прям глубже раскрыть мысль, что в коллекции ну совсем неожиданно встретятся пустые значения.
Да и вообще, похож на английский как никакой другой.

ну и рельсы подали пример как делать: "пишите код с главным приоритетом - удовольствие программиста"
Edited Date: 2016-07-18 01:52 am (UTC)

Date: 2016-07-18 07:25 am (UTC)
From: [identity profile] sassa-nf.livejournal.com
В каком смысле - "литературное программирование"?

expect(blah).to be_falsy например? Так тут как раз нужно помнить, где скобки, где точки, где пробелы, а где подчеркивания :-) Потому что сущности разных видов. И сущности несовместимы с традиционными способами программирования:

x = expect(blah).to
x be_falsy

не работает.

Date: 2016-07-18 09:38 am (UTC)
From: [identity profile] vinslivins.livejournal.com
раньше было проще:
x.should == false (и ничего запоминать не надо) или x.should be_false
(https://www.relishapp.com/rspec/rspec-expectations/v/2-8/docs/built-in-matchers)

но потом пришли пуристы, и теперь это expect(x).to be_falsey
(https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/be-matchers)

(пуристы хотели, чтобы метод should не расширял каждый класс методом should. я тоже хотел. никому не мешало; стало хуже.)

Date: 2016-07-18 09:38 am (UTC)
From: [identity profile] vinslivins.livejournal.com
умный жж мои коменты отправляет в спам

Date: 2016-07-18 12:59 pm (UTC)
From: [identity profile] vinslivins.livejournal.com
на самом деле, идеи там две.

1. в руби любой метод обязан принимать один скрытый аргумент - "блок кода".
он может вызвать это замыкание, а может игнорировать, но отказаться от него нельзя, если передают.

отсюда все конструкции вида

scope { where(username: 'Joe') }
expect { 1 + 1 + 1/0 }

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

цепочка методов тогда будет выглядеть как method1 { code1 }.method2(arg1,arg2) { code2 }.method3 arg1, arg2


2. в руби часто можно опустить скобки.

a b, c, d это a(b,c,d)
a b c d это a(b(c(d)))


Cоответственно, expect(arg1) или expect { code1 } вычисляет значение теста, .to это (не тестировал, но видимо) синтаксический сахар, а дальше идёт сам матчер be(..) от чего угодно.

по идее, так и работает.

Date: 2016-07-18 07:04 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
Какую проблему софтостроения решает передача блока ruby-style? (В отличие от функции в том же руби)

Date: 2016-07-25 08:35 pm (UTC)
From: [identity profile] vinslivins.livejournal.com
хороший правильный вопрос! всю ту же - красивого кода (как if / unless, второй не нужен):

передача блока как замыкания

def f1 blk
blk.call
end

f(proc {..})

передача с красивостями (ровно то же самое по смыслу):

def f1 &blk
blk.call
end

f {..}

Edited Date: 2016-07-25 08:42 pm (UTC)

Date: 2016-07-25 09:21 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
угу, но я бы, скажем, видел смысл в обобщенном случае:

f1 b1 b2 b3,

где все общаются "горизонтально" с помощью, скажем, yield, хотя и в одну сторону. Однако, нет, нету такого.

Date: 2016-07-26 08:34 pm (UTC)
From: [identity profile] vinslivins.livejournal.com
да вроде и не нужно?

Date: 2016-07-26 08:38 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
ну во-первых, может и нужно, а во-вторых, объясняло бы, чем блок от функции отличается.

Пример, где было бы интересно:

readReq process writeResponse

Все три писались бы совсем в другом стиле, а композируются как трубы.

Date: 2016-07-26 08:58 pm (UTC)
From: [identity profile] vinslivins.livejournal.com
не знаю,

readReq.bytes.each_cons(1024).map {|e| ..}.each(|e| STDOUT.write e}


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

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

никакой другой разницы нет, кроме чисто синтаксической.
Edited Date: 2016-07-26 08:59 pm (UTC)

Date: 2016-07-18 09:38 am (UTC)
From: [identity profile] vinslivins.livejournal.com
умный жж мои коменты отправляет в спам

Date: 2016-07-18 09:41 am (UTC)
From: [identity profile] sassa-nf.livejournal.com
хм... не знаю, в инбоксе не показывает дополнительных комментов, кроме тех, что есть здесьа, нашел, расспамил
Edited Date: 2016-07-18 09:43 am (UTC)

Profile

sassa_nf

February 2026

S M T W T F S
1234567
891011121314
15161718192021
222324252627 28

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 22nd, 2026 02:24 am
Powered by Dreamwidth Studios