# Python - Playing with Records - Part Three

Article Series

Playing with Records Related Articles.

Table of Content
Where to Discuss?

Local Group

### Preface

Goal: A simple case example of concurrency using Python.

### Preface

Goal: Continue Part Two

### 7: Approach in Solving Unique

A custom example, that you can rewrite.

#### An Algorithm Case

Why reinvent the wheel?

My intention is writing a custom pattern matching example, so later I can rewrite other algorithm based on this example. You can read the detail on the first article. The record overview.

Consider going back to simple data. We need to discuss about solving unique list.

#### x:xs Pattern Matching

The original `x:xs` pattern matching is made of two functions:

1. Exclude
2. Unique

Pattern matching in `Python`, is not as fancy as `haskell`, or even `OCaml`. But what we have in `Python` is enough, to solve our little problem.

#### Exclude Function

The `exclude` function is just a `filter` with below details:

``````tags = ['60s', 'jazz', '60s', 'rock',
'70s', 'rock', '70s', 'pop']

def exclude(val, tags):
return [tag for tag in tags if tag != val]

print(exclude('rock', tags))``````

With the result as below `array`:

``````❯ python 21-exclude.py
['60s', 'jazz', '60s', '70s', '70s', 'pop']``````

#### Recursive Unique Function

With `exclude` function above, we can build `unique` function recursively, as below code:

``````from MySongs import songs

tags = ['60s', 'jazz', '60s', 'rock',
'70s', 'rock', '70s', 'pop']

def exclude(val, tags):
return [tag for tag in tags if tag != val]

def unique(tags):
if len(tags) <= 1: return tags
else:

print(unique(tags))``````
• Although the syntax looks is, not exactly the same as functional programming in haskell, the algorithm is the same.

With the result as below `array`:

``````❯ python 22-unique-a.py
['60s', 'jazz', 'rock', '70s', 'pop']``````

Now we can apply the method to our unique song challenge.

``````from MySongs import songs

tags = [
tag for song in songs
if 'tags' in song
for tag in song['tags']
]

def exclude(val, tags):
return [tag for tag in tags if tag != val]

def unique(tags):
if len(tags) <= 1: return tags
else:

print(unique(tags))``````
• With the same result as below

``````❯ python 22-unique-b.py
['60s', 'jazz', 'rock', '70s', 'pop']``````

### 8: Generator

Yield

With imperative approach, we can also flatten tags.

We are going to consider this approach for concurrency topic.

#### Yield

Consider this function.

``````def sender(songs):
for song in songs:
if 'tags' in song:
for tag in song['tags']:
yield tag``````

#### Entry Point

Then we can call later:

``````# main: entry point
from pprint import pprint
from MySongs import songs

pprint(list(sender(songs)))``````

With the result of

``````❯ python 24-generator.py
['60s', 'jazz', '60s', 'rock', '70s', 'rock', '70s', 'pop']``````

#### The Skeleton

With above code, we can build the basic of sender receiver function.

``````def receiver():
# ...

def sender():
# ...

# main: entry point
...``````

#### Sender

Yield

It is very similar to our previous function, but we add `None` value as a stopper.

``````def sender(songs):
for song in songs:
if 'tags' in song:
for tag in song['tags']:
yield tag
yield None``````

This `None` value is yielded outside the loop.

Next

Now we can build a while loop that will stop, whenever the value is `None`.

The `next` function will `resume` any yielded value, one value for each `next` call.

``````def receiver(mygenr):
tags = []

while True:
item = next(mygenr)
if item is None:
return tags
else:
if not (item in tags):
tags.append(item)``````

We also test for unique value before appending to tags array.

#### Main

And finally run both function.

``````# main: entry point
from pprint import pprint
from MySongs import songs

mygenr = sender(songs)

With the result as below:

``````❯ python 24-next.py
['60s', 'jazz', 'rock', '70s', 'pop']``````

Now we can have unique tags, with very different approach, compare with our previous list comprehension.

### 9: Concurrency with Queue

`Python` support `Actor Model` pattern. We can rewrite previous process through `queue`.

#### The Skeleton

We should be ready for the real demo. This is only consist of one short file.

``````import threading, queue
from MySongs import songs

q = queue.Queue()
tags = []

# ...

def sender():
# ...

).start()

sender()
q.join()``````
1. Producer: sender()
3. Program entry point: main()

#### Producer and Consumer

We should prepare two functions:

1. One for `Producer` that `put` to `queue`,
2. And the other one for `Consumer` that `get` from `queue`.

`Producer` that `put` to `queue`.

``````def sender():
for song in songs:
if 'tags' in song:
for tag in song['tags']:
q.put(tag)
q.put(None)``````

`Consumer` that `get` from `queue`.

``````def receiver():
while True:
item = q.get()
if item is None:
break
else:
if not (item in tags):
tags.append(item)

#### Running Both Routine

Pretty short right!

Consider gather both function in `main` entry point.

``````def main():
).start()

# block until all tasks are done
sender()
q.join()
print(tags)

main()``````

With the result as below `array`:

``````❯ python 23-queue.py
['60s', 'jazz', 'rock', '70s', 'pop']``````

This is the end of our `python` journey in this article. We shall meet again in other article.

### What is Next 🤔?

Consider continue reading [ Ruby - Playing with Records - Part One ].