Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
[0..100000000000].map { |x| x.prime?}.take(50) for (var i = 0, j = 0; i < 100000000000 && j < 50; i++)
{
if (prime(i))
{
res[j] = i;
j++;
}
}
И если бы в ruby был настоящий сишный for со счетчиком (а не итераторный foreach), то вариант с двумя счетчиками работал бы быстрее
#include int arr[] = {1, 2, 3};
void
test()
{
std::for_each(std::begin(arr), std::end(arr), [](int &elem)
{
elem++;
});
}
cl /FAcs /c /O2 test.cpp
и получаем В ТОЧНОСТИ такой же цикл, как и при "ручном" for:
PUBLIC ?test@@YAXXZ ; test
; Function compile flags: /Ogtpy
; File c:\temp\test\test.cpp
; COMDAT ?test@@YAXXZ
_TEXT SEGMENT
?test@@YAXXZ PROC ; test, COMDAT
; 8 : std::for_each(std::begin(arr), std::end(arr), [](int &elem)
; 9 : {
; 10 : elem++;
; 11 : });
00000 48 8d 05 00 00
00 00 lea rax, OFFSET FLAT:?arr@@3PAHA ; arr
00007 48 8d 0d 0c 00
00 00 lea rcx, OFFSET FLAT:?arr@@3PAHA+12
0000e 66 90 npad 2
$LL15@test:
00010 ff 00 inc DWORD PTR [rax]
00012 48 83 c0 04 add rax, 4
00016 48 3b c1 cmp rax, rcx
00019 75 f5 jne SHORT $LL15@test
; 12 : }
0001b f3 c3 fatret 0
?test@@YAXXZ ENDP ; test
Более того:
#include int arr[] = {1, 2, 3};
void
test(int adder)
{
// Capture adder
auto f = [=](int &elem)
{
elem += adder;
};
// Modify adder
adder = 0;
std::for_each(std::begin(arr), std::end(arr), f);
}
И получаем, что бы Вы думали
PUBLIC ?test@@YAXH@Z ; test
; Function compile flags: /Ogtpy
; File c:\temp\test\test.cpp
; COMDAT ?test@@YAXH@Z
_TEXT SEGMENT
adder$ = 8
?test@@YAXH@Z PROC ; test, COMDAT
; 8 : // Capture adder
; 9 : auto f = [=](int &elem)
; 10 : {
; 11 : elem += adder;
; 12 : };
; 13 :
; 14 : // Modify adder
; 15 : adder = 0;
; 16 :
; 17 : std::for_each(std::begin(arr), std::end(arr), f);
00000 48 8d 05 00 00
00 00 lea rax, OFFSET FLAT:?arr@@3PAHA ; arr
00007 48 8d 15 0c 00
00 00 lea rdx, OFFSET FLAT:?arr@@3PAHA+12
0000e 66 90 npad 2
$LL17@test:
00010 01 08 add DWORD PTR [rax], ecx
00012 48 83 c0 04 add rax, 4
00016 48 3b c2 cmp rax, rdx
00019 75 f5 jne SHORT $LL17@test
; 18 : }
0001b f3 c3 fatret 0
?test@@YAXH@Z ENDP ; test
Серьезно, нет никаких причин, по которым декларативный стиль (с обобщенными алгоритмами и передаваемыми им фунаргами) должен быть медленнее императивного. Но задумайтесь сколько усилий потребуется Вам для императивного написания (а позже и понимания написаного) какого нибудь parallel_for_each или там task<>().then().then().then();#include <algorithm>
int arr[] = {1, 2, 3};
void
test()
{
std::for_each(std::begin(arr), std::end(arr), [](int &elem)
{
elem++;
});
}
PUBLIC ?test@@YAXXZ ; test
; Function compile flags: /Ogtpy
; File c:\temp\test\test.cpp
; COMDAT ?test@@YAXXZ
_TEXT SEGMENT
?test@@YAXXZ PROC ; test, COMDAT
; 8 : std::for_each(std::begin(arr), std::end(arr), [](int &elem)
; 9 : {
; 10 : elem++;
; 11 : });
00000 48 8d 05 00 00
00 00 lea rax, OFFSET FLAT:?arr@@3PAHA ; arr
00007 48 8d 0d 0c 00
00 00 lea rcx, OFFSET FLAT:?arr@@3PAHA+12
0000e 66 90 npad 2
$LL15@test:
00010 ff 00 inc DWORD PTR [rax]
00012 48 83 c0 04 add rax, 4
00016 48 3b c1 cmp rax, rcx
00019 75 f5 jne SHORT $LL15@test
; 12 : }
0001b f3 c3 fatret 0
?test@@YAXXZ ENDP ; test
#include <algorithm>
int arr[] = {1, 2, 3};
void
test(int adder)
{
// Capture adder
auto f = [=](int &elem)
{
elem += adder;
};
// Modify adder
adder = 0;
std::for_each(std::begin(arr), std::end(arr), f);
}
PUBLIC ?test@@YAXH@Z ; test
; Function compile flags: /Ogtpy
; File c:\temp\test\test.cpp
; COMDAT ?test@@YAXH@Z
_TEXT SEGMENT
adder$ = 8
?test@@YAXH@Z PROC ; test, COMDAT
; 8 : // Capture adder
; 9 : auto f = [=](int &elem)
; 10 : {
; 11 : elem += adder;
; 12 : };
; 13 :
; 14 : // Modify adder
; 15 : adder = 0;
; 16 :
; 17 : std::for_each(std::begin(arr), std::end(arr), f);
00000 48 8d 05 00 00
00 00 lea rax, OFFSET FLAT:?arr@@3PAHA ; arr
00007 48 8d 15 0c 00
00 00 lea rdx, OFFSET FLAT:?arr@@3PAHA+12
0000e 66 90 npad 2
$LL17@test:
00010 01 08 add DWORD PTR [rax], ecx
00012 48 83 c0 04 add rax, 4
00016 48 3b c2 cmp rax, rdx
00019 75 f5 jne SHORT $LL17@test
; 18 : }
0001b f3 c3 fatret 0
?test@@YAXH@Z ENDP ; test
foldl1 (+) list. Сложение происходит не итеративно, а рекурсивно. Потому что более краткая форма записи ведет к куда как меньшей вероятности возникновения ошибок в коде, и, когда они все-таки появляются, их (в основном) гораздо проще отловить.
Вы представляете, надо было сделать свою монаду!
-- Аргумент 1 - аккумулятор
-- Аргумент 2 - список нужных индексов
-- Аргумент 3 - список сырых полей
collectFields :: Int -> [Int] -> [String] -> [String]
collectFields _ _ [] = []
collectFields idx fis (s:ss) | idx `elem` fis = s : collectFields (idx+1) fis ss
collectFields idx fis (s:ss) | otherwise = collectFields (idx+1) fis ss
collectFields :: Int -> [Int] -> [String] -> [String]
collectFields idx fis lst = snd $ filter (\(n,_) -> x `elem` fis) $ zip [idx..] ss
filterIndexed :: ((Int,a) -> Bool) -> [a] -> [a]
filterIndexed fun lst = filter fun $ zip [0..] ss
(не)переведена фраза «Personally I find the latter example simpler, clearer, and easier to understand».
import Data.List
a = [1..100]
res = partition odd aa = [1..100]
f :: Int -> ([Int], [Int]) -> ([Int], [Int])
f x (oddXs, evenXs) | odd x = (x : oddXs, evenXs)
| otherwise = (x : oddXs, x : evenXs)
res = foldr f ([], []) a
Хм. Не понятно. Почему иметь три разные конструкции и выстраивать между ними мозговыворачивательные переходники лучше, чем иметь универсальный foldr, который легко подстраивать под конкретную ситуацию?
square(point(0, 0), 20);polyline(point(0,0), point(20,0), point(20,20), point(0, 20));
Что не так с циклами for?