Live data from Hacker News

Streams – Lazy evaluation in C++14

jscheiny.github.io

21–30 of 30 posts

Re: Streams – Lazy evaluation in C++14

#21
post #5

@wwwwwwwwww you have been hell-banned and I dont see anything particularly offensive in your immediate comment history. > is there any reason to add lazy evaluation to c++ [...] I think you are suffering from a misapprehension. Nothing is being added to C++ the language. This is just an implementation of lazy streams in C++14. Think of it as an optional 3rd party library. > lazy evaluation is one of those features wh…

[deleted]

Re: Streams – Lazy evaluation in C++14

#22

honest question: is there any reason to add lazy evaluation to c++ other than to just add more features to the language? lazy evaluation is one of those features where i have absolutely no idea what benefit it actually provides

|| and && operators in C-like languages are "short-circuited", i.e. (true || predicate) just returns (true) without evaluating (predicate). This is a form of lazy evaluation.

Re: Streams – Lazy evaluation in C++14

#23
Seems very close in implementation to RxCPP for push based streams and IxCPP for pull based, which has been created by Microsoft and now controlled by Microsoft Open Technologies. This library though does not require C++14 and is being actively developed: https://github.com/Reactive-Extensions/RxCPP

Re: Streams – Lazy evaluation in C++14

#27

honest question: is there any reason to add lazy evaluation to c++ other than to just add more features to the language? lazy evaluation is one of those features where i have absolutely no idea what benefit it actually provides

I would also like to add that laziness adds a lot of power and flexibility to common procedures.

For example, let's look at a canonical quicksort in Haskell:

  quicksort :: Ord a => [a] -> [a]

  quicksort []     = []

  quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)

      where

          lesser  = filter (= p) xs
This is nothing too interesting, but now let's say you want to write a function to find the minimum value of a list

In Python, this would probably be done like this:

  def min_list(lst):

      current_minimum = lst[0]

      for e in lst[1:]:

          if e 
However, in Haskell, a very similar procedure can be defined like this:

  minimum xs = head (quicksort xs)


(head returns the first element of a list)

Now, if have the slightest care for efficiency, you would never, ever write a function like this in a strict language.

However, in Haskell, minimum [5,2,7,1,3] would be evaluated like this:

  > minimum [5,2,7,1,3]

  > head (quicksort [5,2,7,1,3])
Now, head 'demands' one element from quicksort, so quicksort would start getting evaluated

  > head (lesser ++ ...)  [p = 5]
(++) is nonstrict, and only evaluates the elements you really need. Since right now only one element is demanded, we can expect that nothing to the right of (++) would be evaluated

  > head ((quicksort (filter (
Now filter is also lazy, and it will only evaluate elements as needed. Right now, only one element is demanded by quicksort(notice the (p:xs) in the definition. quicksort only cares about the 'p' right now)

  > head ((quicksort (2:(filter ( head ((quicksort (filter (
Now, quicksort demands another element from filter ( head ((quicksort (1:(filter (Filter will run through the entire list, comparing each element to 5,2 and 1 in order, and find nothing, returning [], which will hit the base case for quicksort []= []

  > head ( [] ++ [1] ++ ...)

Simplifying to

  > head ([1] ++ ...)
(++) has enough evaluated elements to give '1' to head, which finally returns

  > 1

Notice that we passed through the list only once, just like in the python, in contrast to running an entire quicksort. While this is not as efficient as the python version as it keeps a few unnessary elements in memory, and compares elements to all previously found minimums, it is much more efficient than evaluating quicksort, and is pretty damn cool. With some GHC magic, the memory usage is also reduced somewhat.

I personally believe that the expressiveness gained through this procedure(we wrote quicksort and gained minimum for free!) offsets the loss in efficiency.

Re: Streams – Lazy evaluation in C++14

#28
post #20
post #18

Earlier quoted context omitted.

But in a language with mutating side effects, and iterators, I'm not sure what this buys you over: for (auto& num = file.line_iterator(); num != file.end(); num++) { if (atoi(num) == 42) return true; return false; Note that 'line_iterator()' isn't something that (as far as I know) is defined in the C++ standard library, but there's nothing preventing it.

> But in a language with mutating side effects, and iterators, I'm not sure what this buys you... Side-effect free, functional style of programming.

[deleted]

Re: Streams – Lazy evaluation in C++14

#29
post #18
post #16

Earlier quoted context omitted.

>lazy evaluation is one of those features where i have absolutely no idea what benefit it actually provides Good question. Let's say you have a program like this little python example: inputs = [raw_read() for i in range(1000)] # Read numbers from command line numbers = map(int, inputs) # Turn them into integers for num in numbers: # Check for 42 if num == 42: return true return false # It's not there If you use lazy…

But in a language with mutating side effects, and iterators, I'm not sure what this buys you over: for (auto& num = file.line_iterator(); num != file.end(); num++) { if (atoi(num) == 42) return true; return false; Note that 'line_iterator()' isn't something that (as far as I know) is defined in the C++ standard library, but there's nothing preventing it.

Compare the code you wrote with what I wrote.

Lazy evaluation gets you all that, with no extra code, all the time.

Imagine writing that iterator stuff for every single applicable thing in the entire program. There are also other places where lazy evaluation is useful and you can't use iterators, like a function that will only use a portion of its arguments depending on some condition.

Re: Streams – Lazy evaluation in C++14

#30
post #17
post #5

@wwwwwwwwww you have been hell-banned and I dont see anything particularly offensive in your immediate comment history. > is there any reason to add lazy evaluation to c++ [...] I think you are suffering from a misapprehension. Nothing is being added to C++ the language. This is just an implementation of lazy streams in C++14. Think of it as an optional 3rd party library. > lazy evaluation is one of those features wh…

How would this lazy-vector-mapping compare to the optimizations used in std::valarray? Or are those optimizations just the ones you mention here?

Apologies, I did not see your question in time. Note that valarray is just a standard API, an implementer can write it as they wish. That said, these kinds of optimizations were indeed a motivation for creating valarray. Standard libraries do use exactly these optimizations in valarray (with some SIMD vectorization thrown in as well). You can also take a look at pixelglow's implementation, he has a comment downstream. It is pity that no one in the standards committee took ownership of valarray and it was included in a semi broken state.
Post reply on HN