LINUX.ORG.RU

Странное поведение map

 concatenation, , ,


0

1

Почему-то map в «блочном исполнении» синтаксически захватывает в качестве входного списка всё разделённое запятыми, то есть:

$ perl -e '@a=(1,2,3); @b=(4,5,6); @c=map { ">$_<" } @a,@b; print join("\n",@c)."\n"'
>1<
>2<
>3<
>4<
>5<
>6<
Я бы понял, если бы в данном случае такой эффект достигался при указании: map {} (@a,@b), но map объединяет эти списки даже без скобок!

Особенно лютый батхерт эта особенность доставляет при передаче параметров в функцию.

Например, map внутри join...

join("\n",map { $_*$_ } @a,@b)
...вернёт результат преобразования и @a, и @b.

В общем, вопрос околонаучного плана (как обойти это скобками - очевидно) - а почему, собственно, так получается?

★★★★★

Последнее исправление: DRVTiny (всего исправлений: 1)

в качестве входного списка всё разделённое запятыми

Ну, а как он должен отрабатывать это?

map { ... } $val1, $val2, ...;
Где $valN может быть любым типом, например, ссылкой на другую структуру (хэш хэшей).

Ты какую задачу решаешь? Или какое поведение тебе нужно получить?

gh0stwizard ★★★★★
()

С третьего прочтения понял о чём речь =)

map в качестве аргументов ждёт блок и массив, а «@a,@b» это и есть конкатенация массивов, то есть один массив.

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

Мне нужно, чтобы в join(«\n»,map {} @a, @b) - возвращалась строка, в которой map применён только к @a, но не к @b...

DRVTiny ★★★★★
() автор топика

Потому что массив в перле не считается объектом в философском плане, а считается кучей значений через запятую. Если хочешь отделить, юзай референсы — это и есть объекты в питонячьем, например, понимании.

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

Потому что массив в перле не считается объектом в философском плане, а считается кучей значений через запятую. Если хочешь отделить, юзай референсы — это и есть объекты в питонячьем, например, понимании.

Все верно, однако есть вариант идти через прототип функции:

#!/usr/bin/perl

sub mymap(&\@;@) {
  map &{$_[0]}, @{$_[1]};
}

@a = (1..3);
@b = (4..6);

print $_, "\n" for mymap { $_ * $_ } @a, @b;

http://ideone.com/9ZQH6z

Минус в том, что прототип работает только в рамках своего модуля. Извне пример выше надо делать так: mymap(sub { $_ * 3 }, \@list);

gh0stwizard ★★★★★
()
Последнее исправление: gh0stwizard (всего исправлений: 1)
Ответ на: комментарий от gh0stwizard

В каком смысле извне? Так вполне работает

#!/usr/bin/perl

package X;

sub mymap(&\@;@) {
  map &{$_[0]}, @{$_[1]};
}

package main;

@a = (1..3);
@b = (4..6);

print $_, "\n" for X::mymap { $_ * $_ } @a, @b;

Olegymous ★★★
()
perldoc -f join

  join EXPR,LIST

perldoc -f map

  map BLOCK LIST

ты и передаёшь ей список. С чего вдруг ты решил что список должен ограничиваться одним элементом либо с чего вдруг ты решил что передача в список массива чем-то отличается от передачи чего угодно другого?

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