Skip to content
This repository has been archived by the owner on Sep 17, 2022. It is now read-only.

Having a hard time with maps #123

Closed
jaybonthius opened this issue Jan 30, 2022 · 4 comments
Closed

Having a hard time with maps #123

jaybonthius opened this issue Jan 30, 2022 · 4 comments

Comments

@jaybonthius
Copy link

I have a list of hashes called hash_list.

'(
    #hasheq(
      (video . "path/to/example_0000.mp4")
    #hasheq(
      (video . "path/to/example_0001.mp4") 
)

I want to iterate through hash_list and generate a <video src="path/to/my/file.mp4" > for each "video" key.

<video src="path/to/example_0000.mp4"></video>
<video src="path/to/example_0001.mp4"></video>

Here's my attempt:

(define (video_env . text)
    `(video [[src ,text]])
)

(map (λ (hash)
    (video_env (hash-iterate-value hash 0)) )
    hash_list)

I'm getting a decode-elements: contract violation error, where it expects txexpr-elements?, and in the given, I see

... ((video ((src ("path/to/example_0000.mp4")))) (video ((src ("path/to/example_0001.mp4"))))) ...

I might be wrong, but I think decode-elements would be happy if it was given this:

... ((video ((src ("path/to/example_0000.mp4"))))) ((video ((src ("path/to/example_0001.mp4"))))) ...

Regardless, I'm not sure how to fix this. Would anyone mind pointing me in the right direction? Thanks!

@jaybonthius jaybonthius changed the title Having a hard time with loops Having a hard time with maps Jan 30, 2022
@sorawee
Copy link

sorawee commented Jan 30, 2022

Hi!

I have a list of hashes called hash_list.

Note that the code that you wrote has missing parens, and is not a list of hashes. The list of hashes probably should be:

'(#hasheq((video . "path/to/example_0000.mp4"))
  #hasheq((video . "path/to/example_0001.mp4")))

Here's my attempt:

There are two possible mistakes here.

  1. Notice that in the output, you have (video [[src ("path/to/example_0000.mp4")]]). This doesn't make sense, because the attribute src should be associated with a string value, not a list of strings.

    The fix could be done by changing video-env to consume exactly one argument instead of making it consume variadic arguments. That is, you would need to make a definition like this instead:

    (define (video-env text)
      `(video [[src ,text]]))
    

    (Notice the absence of dot. Also, people usually use - instead of _ in names)

  2. Notice that in the output, you have ((video ...) (video ...)). This again doesn't make sense, because the body of the document should not be a list of elements. There are several ways to fix this. One possibility is:

    (apply @ (map .......))
    

So, your final code might look like this:

;; test.html.pm
#lang pollen

◊(define hash-list
  '(#hasheq((video . "path/to/example_0000.mp4"))
    #hasheq((video . "path/to/example_0001.mp4"))))

◊(define (video-env text)
  `(video [[src ,text]]))

◊(define (root . xs)
   (apply @ (map (λ (hash) (video-env (hash-ref hash 'video))) hash-list)))

which produces test.html after raco pollen render test.html.pm

<html>
  <head><meta charset="UTF-8"/></head>
  <body>
    <video src="path/to/example_0000.mp4"></video>
    <video src="path/to/example_0001.mp4"></video>
  </body>
</html>

@jaybonthius
Copy link
Author

@sorawee That did the trick! Thank you so much for pointing out both errors and putting me on the right path. I'm beaming 😄

I dropped some parens in the hash lists when I wrote the question. Whoops!

@mbutterick
Copy link
Owner

mbutterick commented Jan 30, 2022

FWIW:

  • you can avoid using hash tables if you only have one value per record (and just use a flat list).
  • you can avoid defining a tag function if you just want the behavior of default-tag-function.
  • you can avoid using the splicing tag @ explicitly and instead use for/splice (which gathers the results of the iteration under a @ automatically)

So if you wished, you could simplify this example like so:

;; test2.html.pm
#lang pollen

◊(define videos
  '("path/to/example_0000.mp4"
    "path/to/example_0001.mp4"))

◊(for/splice ([v videos])
  (video #:src v))

@jaybonthius
Copy link
Author

@mbutterick My hash table comes from parsing a .json with multiple values per record, which isn't obvious from my oversimplified example. Sorry about that. But your points on default-tag-function and for/splice are taken! And thanks for giving an example, I appreciate it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants