120 lines
3.4 KiB
Scheme
120 lines
3.4 KiB
Scheme
(define recipe-name
|
|
(lambda (recipe)
|
|
(cadr (assoc 'name recipe))))
|
|
|
|
(define recipe-ingredients
|
|
(lambda (recipe)
|
|
(cadr (assoc 'ingredients recipe))))
|
|
|
|
(define recipe-steps
|
|
(lambda (recipe)
|
|
(cadr (assoc 'steps recipe))))
|
|
|
|
(define recipe-servings
|
|
(lambda (recipe)
|
|
(if (recipe-specifies-servings? recipe)
|
|
(cadr (assoc 'servings recipe))
|
|
1)
|
|
))
|
|
|
|
(define ingredient-name
|
|
(lambda (ingredient)
|
|
(if (= (length ingredient) 2)
|
|
(car (cdr ingredient))
|
|
(car (cddr ingredient)))))
|
|
|
|
(define ingredient-amount
|
|
(lambda (ingredient)
|
|
(car ingredient)))
|
|
|
|
(define ingredient-unit
|
|
(lambda (ingredient)
|
|
(if (= (length ingredient) 2)
|
|
""
|
|
(car (cdr ingredient)))))
|
|
|
|
;; Predicates
|
|
|
|
(define contains-ingredient?
|
|
(lambda (search-ingredient recipe)
|
|
(contains-ingredients? (list search-ingredient) recipe)))
|
|
|
|
(define contains-ingredients?
|
|
(lambda (search-ingredients recipe)
|
|
(let ((ingredients (recipe-ingredients recipe)))
|
|
(cond [(null? search-ingredients) #t]
|
|
[(ingredient-by-name (car search-ingredients)
|
|
ingredients)
|
|
(contains-ingredients? (cdr search-ingredients)
|
|
recipe)]
|
|
[else #f])
|
|
)))
|
|
|
|
(define recipe-specifies-servings?
|
|
(lambda (recipe)
|
|
(assoc 'servings recipe)))
|
|
|
|
;; Searching and indexing
|
|
|
|
(define ingredient-ref
|
|
(lambda (ingredients n)
|
|
(if (= n 0)
|
|
(car ingredients)
|
|
(ingredient-ref (cdr ingredients) (- n 1)))))
|
|
|
|
(define ingredient-by-name
|
|
(lambda (search-name ingredient-list)
|
|
(let ((ingredient (car ingredient-list)))
|
|
(cond [(equal? (ingredient-name ingredient)
|
|
search-name)
|
|
ingredient]
|
|
[(null? (cdr ingredient-list)) #f]
|
|
[else (ingredient-by-name search-name
|
|
(cdr ingredient-list))]))))
|
|
|
|
(define recipes-by-ingredients
|
|
(lambda (search-ingredients recipes)
|
|
(filter (lambda (x) (contains-ingredients? search-ingredients x))
|
|
recipes)))
|
|
|
|
(define recipe-by-name
|
|
(lambda (name recipes)
|
|
(if (null? recipes)
|
|
#f
|
|
(let ((recipe (car recipes)))
|
|
(if (equal? (recipe-name recipe)
|
|
name)
|
|
recipe
|
|
(recipe-by-name name (cdr recipes)))))))
|
|
|
|
;; Manipulation
|
|
|
|
(define scale-recipe-by-servings
|
|
(lambda (wanted-servings recipe)
|
|
(let ([name (recipe-name recipe)]
|
|
[ingredients (recipe-ingredients recipe)]
|
|
[steps (recipe-steps recipe)]
|
|
[servings (recipe-servings recipe)])
|
|
(let ([new-name name]
|
|
[new-ingredients (map (lambda (ingr)
|
|
(cons (* (/ (car ingr)
|
|
servings)
|
|
wanted-servings)
|
|
(cdr ingr)))
|
|
ingredients)]
|
|
[new-steps steps]
|
|
[new-servings wanted-servings])
|
|
(make-recipe new-name new-servings new-ingredients new-steps)
|
|
))))
|
|
|
|
(define scale-recipe-by-factor
|
|
(lambda (scale-factor recipe)
|
|
(let ([new-servings (* (recipe-servings recipe) scale-factor)])
|
|
(scale-recipe-by-servings new-servings recipe))))
|
|
|
|
;; Constructors
|
|
|
|
(define make-recipe
|
|
(lambda (name servings ingredients steps)
|
|
`((name ,name) (servings ,servings) (ingredients ,ingredients) (steps ,steps))))
|