1 / 33

five

five. implementing streams using classes. Exercise 1. [repeat list count ] Returns count copies of list , in order [random-pattern count elements … ] Returns a list of count objects randomly chosen from elements. Limitations of lists. What wrong with these?

Download Presentation

five

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. five implementing streams using classes

  2. Exercise 1 • [repeat list count] • Returns count copies of list, in order • [random-pattern count elements …] • Returns a list of count objects randomly chosen from elements

  3. Limitations of lists • What wrong with these? • [repeat [list 1 2 3 4]∞] • [random-pattern ∞ 1 2 3 4 5] • SuperCollider lets you make patterns that run infinitely • But lists have to be finite length because they store all the elements in memory at once • And memory is finite

  4. Streams • Streams are like lists • They “contain” a set of objects • In a specified order • But unlike lists • You can’t ask for an arbitrary elelement (i.e. you can’t to get or second) • You can only ask for the “next” element • On the other hand, they can be infinitely long

  5. The basic idea • Rather than storing all the elements in memory at once • We store just enough information to figure out what the next element should be • And then run code to figure it out each time we need a new element

  6. Implementing streams using classes • Make a “base class” called Stream • Implement different Pseq, etc. operators as subclasses of stream • Each stream supports two generic functions • [next-element s]Returns the next element of s • [reset s]Goes back to the first element • [done? s]Returns true is s has no more elements Stream ListStream RandomStream JoinedStream RandomStreamNoRepeats

  7. Last time • [class [Name fields …]Parent-typeadditional-fields …] • Creates a new data type • Has all the fields of Parent-type, plus fields, and additional-fields • Note: last week, this was called “class-type”; I’ve decided to shorten the name • [new Type field-values …] • Creates a new data object of the specified Type (class) • Field-values are used as values for fields mentioned in the class definition, but not additional-fields.

  8. Last time • [generic-procedure] • Makes a kind of procedure whose behavior depends on the types of its arguments • [define-method [generic [type arg] …]code …] • Specifies what code to run a generic procedure is given arguments with a certain set of types • When each arg is passed a value of its respective type, then code is run.

  9. Code for the base class [using Packages.SimpleClasses] [define Stream [class [Stream] Object]]] [define next-element [generic-procedure]] [define reset[generic-procedure]] [define done? [generic-procedure]]

  10. The ListStream class • Simple example • Idea: make a stream from a list • [new ListStream list]Should return a stream that will generate each of list, in order, and then end

  11. Code for the ListStream class [define ListStream [class [ListStream list] Stream position]] [define-method [reset [ListStream s]][s.position ← 0]] [define-method [next-element [ListStream s]][with answer = [get s.list s.position] [s.position ← [+ s.position 1]] answer]] [define-method [done? [ListStream s]][= s.position [length s.list]]]

  12. Initializing objects [define ListStream [class [ListStream list] Stream position]] • Okay we know that the list field gets its value from the call to new: [new ListStream list] • But what value does position get? • Answer: null • This is a pain, because we need position to be a number

  13. The initialize generic procedure [define-method [initialize [ListStream s]] [s.position ← 0]] • When an object is created • Meta calls the initialize procedure on it • Before returning it from new • So you can provide any special code you want to run by providing a method for your new class

  14. But wait … [define-method [initialize [ListStream s]] [s.position ← 0]] [define-method [reset [ListStream s]][s.position ← 0]] • This is the same code as reset…

  15. But wait … [define-method [initialize [ListStream s]] [reset s]] [define-method [reset [ListStream s]][s.position ← 0]] • So why not just have initialize call reset?

  16. But wait … [define-method [initialize [Stream s]] [reset s]] [define-method [reset [ListStream s]][s.position ← 0]] • In fact, we can make it a method for the whole Stream class, not just for ListStreams • It will still run for ListStreams because they’re a kind of Stream

  17. Random streams • ListStreams don’t let us do anything we couldn’t do with lists • Let’s think about how to implement the random streams in such a way that the streams can be “infinite” • [new RandomStream list-of-elements desired-length] • Should generate a stream of desired-length elements from list-of-elements • The objects need to store • The list of objects to choose (randomly) from • The number of objects we’ve generated • The number of objects we need to generate

  18. RandomStream code [define RandomStream [class [RandomStream list desired-length] Stream current-count]] [define-method [reset [RandomStream s]][s.current-count ← 0]] [define-method [done? [RandomStream s]][= s.current-count s.desired-length]] [define-method [next-element [RandomStream s]][s.current-count ← [+ s.current-count 1]][get s.list [random-integer 0 [length s.list]]]] Note no initialize method Why?

  19. Testing it out [define stream→list[stream max-length → [with elements = [new System.Collections.ArrayList] count = 0 [while [and [< count max-length] [not [done? stream]]] [count ← [+ count 1]] [elements.Add [next-element stream]]] elements]]] • We need some way of testing out whether it works • The easiest way is to make a procedure that will read a list of numbers from the stream and print them

  20. Testing it out ► [stream→list [new RandomStream [list 1 2 3] ∞] 20] [2 2 1 3 3 3 2 3 1 3 3 2 1 1 1 3 2 2 1 1] ►

  21. Random without repeats • Now let’s do the equivalent of SuperCollider’s Pxrand • All we need to do is • Remember one additional piece of information: the last number we generated • Change the next-element method

  22. RandomStreamNoRepeats code [define RandomStreamNoRepeats [class [RandomStreamNoRepeats list desired-length] RandomStream last-value]] [define-method [reset [RandomStreamNoRepeats s]][s.last-value ← null][call-next-method]] [define-method [next-element [RandomStreamNoRepeats s]][with new-value = s.last-value [while [= new-value s.last-value] [new-value ← [get s.list [random-integer 0 [length s.list]]]]] [s.last-value ← new-value] new-value]]

  23. Testing it out ► [stream→list [new RandomStreamNoRepeats [list 1 2] 100] 20] [1 1 1 2 2 2 1 1 2 2 2 2 2 1 2 2 2 1 1 1] • Oops….

  24. RandomStreamNoRepeats code [define RandomStreamNoRepeats [class [RandomStreamNoRepeats list desired-length] RandomStream last-value]] [define-method [reset [RandomStreamNoRepeats s]][s.last-value ← null][call-next-method]] [define-method [next-element [RandomStreamNoRepeats s]][with new-value = s.last-value [while [= new-value s.last-value] [new-value ← [get s.list [random-integer 0 [length s.list]]]]] [s.current-count ← [+ s.current-count 1]][s.last-value ← new-value] new-value]]

  25. Testing it out ► [stream→list [new RandomStreamNoRepeats [list 1 2] 100] 20] [1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2] • Oops….

  26. RandomStreamNoRepeats code [define RandomStreamNoRepeats [class [RandomStreamNoRepeats list desired-length]RandomStream last-value]] [define-method [reset [RandomStreamNoRepeats s]][s.last-value ← null][call-next-method]] [define-method [next-element [RandomStreamNoRepeats s]][with new-value = s.last-value [while [= new-value s.last-value] [new-value ← [get s.list [random-integer 0 [length s.list]]]]] [s.current-count ← [+ s.current-count 1]] [s.last-value ← new-value] new-value]] This time, the parent class is RandomStream

  27. RandomStreamNoRepeats code [define RandomStreamNoRepeats [class [RandomStreamNoRepeats list desired-length] RandomStream last-value]] [define-method [reset [RandomStreamNoRepeats s]][s.last-value ← null][call-next-method]] [define-method [next-element [RandomStreamNoRepeats s]][with new-value = s.last-value [while [= new-value s.last-value] [new-value ← [get s.list [random-integer 0 [length s.list]]]]] [s.current-count ← [+ s.current-count 1]] [s.last-value ← new-value] new-value]] Notice there’s no done? method Why?

  28. RandomStreamNoRepeats code [define RandomStreamNoRepeats [class [RandomStreamNoRepeats list desired-length] RandomStream last-value]] [define-method [reset [RandomStreamNoRepeats s]][s.last-value ← null][call-next-method]] [define-method [next-element [RandomStreamNoRepeats s]][with new-value = s.last-value [while [= new-value s.last-value] [new-value ← [get s.list [random-integer 0 [length s.list]]]]] [s.current-count ← [+ s.current-count 1]] [s.last-value ← new-value] new-value]] calls the method of the parent class (so we don’t need to init s.current-count)

  29. Pasting streams together • Now we need a way to paste streams together • We just make a new class • That remembers the list of streams to paste together • And its position in the list • And calls the substreams’ next-element methods to get new elements • [new JoinedStream list-of-streams] • Should return a stream that generates all the elements of all the streams

  30. JoinedStream class [define JoinedStreams [class [JoinedStreams stream-list] Stream position]] [define-method [reset [JoinedStreams j]][for-each reset j.stream-list][j.position ← 0]] • To reset the stream, we reset all the substreams • Now, how do we figure out if we’re done?

  31. The done? method [define-method [done? [JoinedStreams j]] [and [= j.position [− [length j.stream-list] 1]] [done? [get j.stream-list j.position]]]] • Check that we’re on the last substream • And the last substream is done • How do we generate the next element?

  32. The next-element method [define-method [next-element [JoinedStreams j]][when [done? [get j.stream-list j.position]] [j.position ← [+ j.position 1]]][next-element [get j.stream-list j.position]]] • We check whether we need to move on to the next stream yet • Note that when is a variant of if that doesn’t take an else clause • Then we generate an element from whatever the current stream is

  33. Testing it out ► [stream→list [new JoinedStreams [list [new ListStream [list 3 2 1]] [new RandomStreamNoRepeats [list 1 2] 100]]] 20] [3 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2] • It works! ListStream RandomStreamNoRepeats

More Related