dluciv: (линейка)
[personal profile] dluciv
В Котлине, если ты хочешь сделать функцию с локальными переменными, придётся возвращать значение при помощи return.

fun bugaga() {
  val z = 5
  return z
}



Я это конечно объехал, но код на мой вкус красивее не стал =):

fun bugaga() = when(true) { else -> {
  val z = 5
  z
}}


Ещё можно написать, как иногда пишут на JS, и надеяться, что заинлайнит лямбду:

fun bugaga() = ({
  val z = 5
  z
}())


Для этого даже есть специальная затычка run, чтобы выглядело немного пристойнее (скобок меньше):

fun bugaga() = run {
  val z = 5
  z
}


Из сказанного выше уже становится понятно, что Котлин очень хочет из любых фигурных скобок сделать лямбду. Оно на самом деле так и есть. Если в середине тела функции попытаться сделать использовать фигурные скобки, как выражение, то тоже получится не то, что считается в них, а функция, которая считает то, что в них.

Наконец, можно просто присвоить лямбду в переменную/константу, написав:


val bugaga = {
  val z = 5
  return z
}


В какую жесть это выльется, см. в комментах.

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

Или я чего-то очень-очень не догнал (надеюсь), причём не я один, а ещё как минимум один мужик, или Котлин пилили фанаты goto...

Date: 2015-11-13 03:18 pm (UTC)
From: [identity profile] juan-gandhi.livejournal.com
А лямбды там есть?

Date: 2015-11-13 03:29 pm (UTC)
From: [identity profile] dluciv.livejournal.com
Есть.

val bugaga = { ->
    val y = 4
    y
}


fun main(args: Array) {
    println("Hello, world! " + bugaga())
}


Только заставить такую лямбду стать методом класса как-то я тоже не осилил...

Т.е. можно сделать, как в JS делают полноценные this-bound функции, но сгенерится из этого просто аттрибут с геттером, который вернёт самодостаточную замкнутую функцию:

class C {
    public var i = 5
    public val f = { j: Int ->
        val r = i + j
        r
    }
}

fun main(args: Array) {
    val c = C()
    c.i = 7
    println(c.f(3))
}


В c.f -- вызывается на самом деле геттер getF, который вернёт kotlin.jvm.functions.Function1<int, int>, и у которого потом вызовут .invoke(3).

Можно собственно ещё более похоже на то, что делают с JS, написать (тоже работает, но блин...)

class C {
    public var i = 5
    public fun f(j: Int): Int = ({
        val r = i + j
        r        
    }())
}


Собственно я решил, что match оно надёжнее пооптимизит. Лямбду тоже может конечно заинлайнить, но не факт.
Edited Date: 2015-11-13 04:34 pm (UTC)

Date: 2015-11-13 03:36 pm (UTC)
From: [identity profile] kouzdra.livejournal.com
А чем он вообще хорош? Я смотрел - и как-то так и не понял.

PS: То есть про Скалу понимаю - хотя уродец тоже тот еще, а с этим вот так и не понял.
Edited Date: 2015-11-13 03:36 pm (UTC)

Date: 2015-11-13 03:42 pm (UTC)
From: [identity profile] dluciv.livejournal.com
Ну в принципе он довольно неплохо в руках что-ли сидит...
В том смысле, в котором Питон, например, или Ruby.

В нём в стиле Idea -- много хаков, которые хорошо и удобно втыкаются в конкретные места. Например он из тй же лямбды может статически генерить, если прорюхает тип, какой-нибудь Listener с единственным абстрактным методом. В мэтче по типу может в конкретных ветках полностью использовать знания о типе (Алгол 68 тоже вроде умел). Ну и тому подобное.

Но восхищения не вызывает, нет.

Date: 2015-11-13 04:06 pm (UTC)
From: [identity profile] kouzdra.livejournal.com
В матче по типу много умеет - начится с Симулы-67 и кончая Go. Это у Жабы только кажется такое странное чистоплюйство

Date: 2015-11-13 04:11 pm (UTC)
From: [identity profile] dluciv.livejournal.com
Да ладно... В Жабе матча по типу вообще по-моему нет. Потом вроде ML и друзья не умеют. Что подзадалбывает местами.

Т.е. вот:


match v with
  | C1(x) -> ....код не может пользоваться v, как C2...
  | С2(y, z) as c2 -> ... код может пользоваться c2, но не v, как C2...

Date: 2015-11-13 04:18 pm (UTC)
From: [identity profile] kouzdra.livejournal.com
В ML матча по типу тоже нет - но по другой причине - он там
1) не нужен
2) нереализуем в принципе

match v with
  | C1(x) -> ....код не может пользоваться v, как C2...
  | С2(y, z) as c2 -> ... код может пользоваться c2, но не v, как C2...


Так в ML С1 и C2 - не типы. А у c2 тип ровно тот же что у v - то есть это тут бессмысленная тавтология

Date: 2015-11-13 04:26 pm (UTC)
From: [identity profile] dluciv.livejournal.com
Ну мы друг друга насчёт матча по типу поняли.

В F# (остальных давно не тискал) про c2 будет известно, что это конкретный вариант со всеми его фишками. А про v -- только что это тип, у которого такой вариант есть. Я это имел в виду.
Edited Date: 2015-11-13 04:28 pm (UTC)

Date: 2015-11-21 06:17 pm (UTC)
From: [identity profile] dluciv.livejournal.com
Алсо, ради справедливости, Скала -- хоть я и не испытываю, глядя на неё, безумного упоения -- всё ж нормальный язык.

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

Date: 2015-11-22 06:23 am (UTC)
From: [identity profile] kouzdra.livejournal.com
На это кстати еще в А-68 налетели - там в первоначальной версии было "запроцедуривание" - именно что параметр в контексте требующем лямбду в нее автоматически заворачивался - но вышла такая жопа что в "пересмотренном" А-68 это выкинули.

September 2017

S M T W T F S
     12
34 56789
10111213 14 1516
17181920212223
24252627282930

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 21st, 2017 05:32 pm
Powered by Dreamwidth Studios