Article Series

This article series discuss more than 30 different programming languages. Please read overview before you read any of the details.

Playing with Records Related Articles.

Preface

Goal: Finishing the task, using functional approach.


8: Approach in Solving Unique

A custom example, that you can rewrite.

An Algorithm Case

Why reinvent the wheel?

The same reason as any other articles.

x:xs Pattern Matching

The same with any other articles as well.

Remove Element from List

Guile has this built in delq.

(define tags (list
  "rock" "jazz" "rock" "pop" "pop"))

(display (string-join (delq "rock" tags) ":"))
(newline)

With the result as below list:

❯ guile 11-exclude-a.scm
jazz:pop:pop

Guile: Exclude Function

Exclude Function

For practice purpose, we can bundle the code in it own subroutine.

(define tags (list
  "rock" "jazz" "rock" "pop" "pop"))

(define
  (delq-clone value tags)
  (delq value tags)
)

(display (string-join
  (delq-clone "rock" tags) ":"))
(newline)

With the result exactly the same as previous code.

Guile: Exclude Function

You don’t need this exclude function. It is just a demonstration of writing a function, along with its argument. We are going to understand the basic, before writing recursive unique function later.


9: Preparing Unique Function

I’l be kind. My reader might be a beginner. So I explain step by step.

Guard

There is no need to process unique list, for list with just one member, so we need to differ the process result using conditional, as shown in code below:

(use-modules (oop goops))

(define my-tags (list
  "rock" "jazz" "rock" "pop" "pop"))

(define-method
  (unique-guard (tags <list>))
  (if
    (<= (length tags) 1)
    (tags)
    (cdr tags)
  ))

(display (unique-guard my-tags))
(newline)

With the result as below list:

❯ guile 12-unique-a.scm
(jazz rock pop pop)

Guile: Preparing Unique Function: Guard

Notice goops module required for further code subroutine signature.

Head and Tail

Our recursive function require this variable:

  • Head and Tail
  • Excluded list, based on head and tail above.

Preliminary code can be written as below:

(use-modules (oop goops))

(define my-tags (list
  "rock" "jazz" "rock" "pop" "pop"))

(define-method
  (unique-var (tags <list>))
  (let
    ( (head (car tags)) (tail (cdr tags)) )
    (let ( (xcld (delq head tail)) )
      (begin
        (display head) (newline)
        (display tail) (newline)
        (display xcld) (newline)
))))

(unique-var my-tags)

Now examine the result carefully:

❯ guile 12-unique-b.scm
rock
(jazz rock pop pop)
(jazz pop pop)

Guile: Preparing Unique Function: Head and Tail

Combine Guard and Head:Tail

Consider combine both codes.

(use-modules (oop goops))

(define my-tags (list
  "rock" "jazz" "rock" "pop" "pop"))

(define-method
  (unique-var (tags <list>))
  (if
    (<= (length tags) 1)
    (tags)
    (let
      ( (head (car tags)) (tail (cdr tags)) )
      (let ( (xcld (delq head tail)) )
        (begin
          (display head) (newline)
          (display tail) (newline)
          (display xcld) (newline)
)))))

(unique-var my-tags)

With the result exactly the same as previous code.

Guile: Preparing Unique Function: Combined

Recursive Unique Value

After head:tail, we can go further getting unique value.

(use-modules (oop goops))

(define my-tags (list
  "rock" "jazz" "rock" "pop" "pop"))

(define-method
  (unique (tags <list>))
  (if
    (<= (length tags) 1)
    (begin
      (display tags) (newline)
      tags)
    (let
      ( (head (car tags)) (tail (cdr tags)) )
      (let 
        ( (xcld (delq head tail)) )
        (let
          ( (uniq (unique xcld)) )
          (begin
            (display (append (list head) uniq))
            (newline)
            (append (list head) uniq)
))))))

(unique my-tags)
(newline)

Again, examine the result carefully:

❯ guile 12-unique-d.scm
()
(pop)
(jazz pop)
(rock jazz pop)

Guile: Preparing Unique Function: Recursive Value

We already have our unique value. We need to clean up the subroutine.


10: Recursive Unique Function

Since we are going to reuse the unique approach in other script. It is better to bundle the script in its own guile module.

Clean Up

The cleaned-up version of previous code will be as below

(define my-tags (list
  "rock" "jazz" "rock" "pop" "pop"))

(define (unique tags)
  (if (<= (length tags) 1)
    tags
    (let
      ( (head (car tags)) (tail (cdr tags)) )
      (append (list head)
        (unique (delq head tail)))
)))

(display (string-join (unique my-tags) ":"))
(newline)

The return values is a list.

(append (list head)
  (unique (delq head tail)))

With the result as below list.

❯ guile 13-unique-e.scm
rock:jazz:pop

Guile: The Unique Function: Cleaned Up

Recursive Unique Function

Just like our previous flatten module, we can just copy paste the unique subroutine, into its own unique module.

(define-module (my-helper-unique))

(define-public (unique tags)
  (if (<= (length tags) 1)
    tags
    (let
      ( (head (car tags)) (tail (cdr tags)) )
      (append (list head)
        (unique (delq head tail)))
)))

Guile: The Unique Function: Module

Using Unique Module

There is nothing to say in this code below. Just apply unique function to our song records.

(add-to-load-path
  (dirname (current-filename)))
(use-modules (my-helper-unique))

(define my-tags (list
  "rock" "jazz" "rock" "pop" "pop"))

(display (string-join (unique my-tags) ":"))
(newline)

With the result as below list:

❯ guile 13-unique-f.scm
rock:jazz:pop

Guile: Using Recursive Unique Function

Applying Unique to Songs Records

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

(add-to-load-path
  (dirname (current-filename)))
(use-modules (my-songs))
(use-modules (my-helper-flatten))
(use-modules (my-helper-unique))

(display (string-join
  (unique (flatten songs)) ":"))
(newline)

With the same result as below

Guile: Solving Unique Song

❯ guile 13-unique-g.scm
60s:jazz:rock:70s:pop

We are done solving our challenge.

Style Guide

Forgive my indentation.

For those who care a lot about style, you can read this material below:

Summary

For convenience, I put all the code in just one screenshot figure as below:

Guile: Solving Unique Song: Wide Summary

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


What is Next 🤔?

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