LINUX.ORG.RU

HOF в Руби


0

0

Уважаемые, есть ли способ передать в руби функцию в качестве аргумента другой функции? То есть примерно так:

def cmp(a,b): a > b

def mykewlsort(f,arr): [тут сортировка с использованием f в качестве упорядочивающей фукнции]

mykewlsort(cmp, [1,2,3])

?

Ведь просто 'cmp' это вызов cmp с пустыми параметрами. Гуглёж выдаёт какие-то сумасшедшие способы. Однако, кмк, должны быть простейшие способы так сделать, иначе какой же это acceptable lisp?


прошу прощения за питонизм в виде ':' после заголовков функций %)

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

А разница? :)

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

def cmp(a, b)
	a > b
end

def mykewlsort(arr, &f)
	if arr.respond_to?(:length)
		for i in 0...(arr.length - 1)
			if f.call(arr[i], arr[i + 1])
				arr[i], arr[i + 1] = arr[i + 1], arr[i]
			end
		end
	end
end

arr = [1,3,2]
mykewlsort(arr){|a, b| cmp(a, b)}
puts arr
Deleted
()
Ответ на: комментарий от kkw

Callback вообще можно как раз делать замыканиями. Отрывок из кода одного класса:

card['abilities'].each do |ability|
    case ability['name']
        when 'damage'
            each_target(current_hero, other_hero, ability['target'], position) do |t|
                t.do_damage!(ability['param'].to_i, :magic)
            end
        end
end
def each_target(current_hero, other_hero, target, position)
    current_field = current_hero.field
    other_field = other_hero.field

    case target
        # your hero and creatures
        when 'self:all'
            current_field.position.each { |slot| yield slot unless slot.empty? }
            yield current_hero

        # your creatures
        when 'self:creatures'
            current_field.position.each { |slot| yield slot unless slot.empty? }
    end
end
Deleted
()
Ответ на: комментарий от Deleted

Ну разница в том, что это две разных вещи :)

Ты явно указываешь в этой строчке "mykewlsort(arr){|a, b| cmp(a, b)}", что используеться функция cmp. А мне надо её просто передать. То есть, например, у меня есть только указатель на неё (в переменной).

Да, кстати, еще вопрос. Как положить функцию в переменную? Типа вот так: a = null; function kewlfunc() { ... }; a = kewlfunc;

kkw
() автор топика
Ответ на: комментарий от Deleted

Вот. Я тоже нашел такое "решение". Но это ведь не лямбда совсем. Да и для такой простой хреновины городить так много слов? Не понятно. Я уверен, есть более хорошие способы.

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

Ну почему же, вполне :)

А вообще, посмотрим, может кто решение получше предложит.

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

А в чём там многословность? Замени do / end на { } если так меньше букв :)

Deleted
()

Нету в руби такого напрямую, потому что Мацумото смолток в голову ударил, и он решил, что методы - это не объекты. Зато есть 1001 способ сделать это чирижжопу, потому что перл ему тоже в голову ударил.

kot_otbelivatel
()

Ха-ха, руби хуже, чем я думал :)

Sphinx ★★☆☆
()

спокойствие, только спокойствие. я уже здесь.

def mycmp(a); a.max; end
def mymetasomething(meth, ary); meth.call(ary); end
mymetasomething(method(:mycmp),[1,2,3])

справедливости ради: в руби, в отличие от питона, этим почти не пользуются.

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

>Нету в руби такого напрямую, потому что Мацумото смолток в голову ударил, и он решил, что методы - это не объекты.

Ты таки не прав. Методы - это объекты класса Method.

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

Символы… /me посыпает голову пеплом :}

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

>справедливости ради: в руби, в отличие от питона, этим почти не пользуются.

вы так говорите, как будто это что-то плохое

z0D5e8n7x_2
()

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

Идеологически правильное решение для руби - сварганить объект-функтор с функцией сравнения и перегружать его метод в своё удовольствие без всякого насилия мозга. Передавать в функцию объект и сравнивать его методом. Иначе будет хреново поддерживаемый код, типа http://www.linux.org.ru/jump-message.jsp?msgid=4234403&cid=4238253

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

>Иначе будет хреново поддерживаемый код, типа http://www.linux.org.ru/jump-message.jsp?msgid=4234403&cid=4238253

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

Идеологически правильное решение для руби - ..

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

</thread>

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

> таки использовать блоки и yield.

Верно в целом, но не применимо к этой задаче. Здесь нужна _именованная_ функция.

Вот теперь уже </thread>.

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